summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Young <chris@unsatisfactorysoftware.co.uk>2018-01-12 23:21:58 +0000
committerChris Young <chris@unsatisfactorysoftware.co.uk>2018-07-23 18:41:06 +0100
commit8614f549b79ac6d9d079efc85a735d0c092ff3e8 (patch)
treef23975e797be5d1764501a956b74e8c1a6c8a83a
parentbac3e0ec6390348d2d1f44f0fb7ef5e2c43f74d3 (diff)
downloadtoolchains-8614f549b79ac6d9d079efc85a735d0c092ff3e8.tar.gz
toolchains-8614f549b79ac6d9d079efc85a735d0c092ff3e8.tar.bz2
Update to gcc 6.3
using bebbo's patches (generated from github.com/bebbo/gcc)
-rw-r--r--m68k-unknown-amigaos/Makefile2
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/configure.p12
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.Makefile.in.p133
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.c-decl.c.p87
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.c-incpath.c.p19
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.c-parse.in.p223
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.c-tree.h.p13
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.calls.c.p24
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.collect2.c.p200
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.common.opt.p17
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.gcc.p17
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.host-linux.c.p11
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.host.p14
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.m68k.m68k-protos.h.p14
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.m68k.m68k.c.p513
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.m68k.m68k.h.p175
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.m68k.m68k.md.p82
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.configure.ac.p35
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.configure.p61
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.cppfiles.c.p48
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.defaults.h.p13
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.fixinc.mkfixinc.sh.p10
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.flow.c.p19
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.function.c.p31
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.function.h.p11
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.gcc.c.p63
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.ginclude.stdarg.h.p20
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.loop.c.p13
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.mklibgcc.in.p13
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.opts.c.p26
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.rtl.h.p11
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc.toplev.c.p11
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gcc6.p42963
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/gmp-configure.p11
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/include.filenames.h.p14
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/libiberty.configure.p105
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/libiberty.lbasename.c.p13
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/libiberty.make-temp-file.c.p27
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/libiberty.pex-unix.c.p13
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/libiberty.strsignal.c.p13
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/libstdc++-v3.config.cpu.m68k.atomicity.h.p25
-rw-r--r--m68k-unknown-amigaos/recipes/patches/gcc/libstdc++-v3.configure.p13
42 files changed, 42964 insertions, 2174 deletions
diff --git a/m68k-unknown-amigaos/Makefile b/m68k-unknown-amigaos/Makefile
index 8597dcf..3aaf896 100644
--- a/m68k-unknown-amigaos/Makefile
+++ b/m68k-unknown-amigaos/Makefile
@@ -3,7 +3,7 @@
# sources
-UPSTREAM_GCC_VERSION := 3.4.6
+UPSTREAM_GCC_VERSION := 6.2.0
UPSTREAM_GCC_TARBALL := gcc-$(UPSTREAM_GCC_VERSION).tar.bz2
UPSTREAM_GCC_URI := http://ftp.gnu.org/gnu/gcc/gcc-$(UPSTREAM_GCC_VERSION)/$(UPSTREAM_GCC_TARBALL)
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/configure.p b/m68k-unknown-amigaos/recipes/patches/gcc/configure.p
deleted file mode 100644
index 2561988..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/configure.p
+++ /dev/null
@@ -1,12 +0,0 @@
---- gcc-3.4.6/configure 2013-05-19 20:08:05.000000000 +0200
-+++ configure 2013-05-19 20:23:32.000000000 +0200
-@@ -1060,6 +1060,9 @@
- *-*-cygwin*)
- noconfigdirs="autoconf automake send-pr rcs guile perl"
- ;;
-+ m68k-*-amigaos*)
-+ noconfigdirs="$noconfigdirs texinfo"
-+ ;;
- *-*-netbsd*)
- noconfigdirs="rcs"
- ;;
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.Makefile.in.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.Makefile.in.p
deleted file mode 100644
index 2564f97..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.Makefile.in.p
+++ /dev/null
@@ -1,133 +0,0 @@
---- gcc-3.4.6/gcc/Makefile.in 2013-05-19 20:08:05.000000000 +0200
-+++ gcc/Makefile.in 2013-05-19 20:23:32.000000000 +0200
-@@ -541,10 +541,36 @@
- # List of additional header files to install.
- EXTRA_HEADERS =@extra_headers_list@
-
-+### begin-GG-local
-+# List of extra targets that should be executed by make when building
-+# the `doc' target.
-+EXTRA_DOC_TARGETS =
-+### end-GG-local
-+
-+### begin-GG-local
-+# List of extra targets that should be executed by make when building
-+# targets `stage1' to `stage4'.
-+EXTRA_STAGE1_TARGETS =
-+EXTRA_STAGE2_TARGETS =
-+EXTRA_STAGE3_TARGETS =
-+EXTRA_STAGE4_TARGETS =
-+### end-GG-local
-+
- # It is convenient for configure to add the assignment at the beginning,
- # so don't override it here.
- USE_COLLECT2 = collect2$(exeext)
-
-+### begin-GG-local: dynamic libraries
-+# List of extra object files that should be compiled and linked with
-+# collect2.
-+EXTRA_COLLECT2_OBJS =
-+### end-GG-local
-+
-+### begin-GG-local
-+# List of extra targets that should be executed by make when installing.
-+EXTRA_INSTALL_TARGETS =
-+### end-GG-local
-+
- # List of extra C and assembler files to add to static and shared libgcc2.
- # Assembler files should have names ending in `.asm'.
- LIB2FUNCS_EXTRA =
-@@ -651,6 +677,11 @@
- # at build time.
- SPECS = specs
-
-+# Even if ALLOCA is set, don't use it if compiling with GCC, unless
-+# a configuration file overrides this default.
-+USE_ALLOCA= ` case "${CC}" in "${OLDCC}") echo "${ALLOCA}" ;; esac `
-+USE_HOST_ALLOCA= ` case "${HOST_CC}"@"${HOST_ALLOCA}" in "${OLDCC}"@?*) echo ${HOST_PREFIX}${HOST_ALLOCA} ;; esac `
-+
- # End of variables for you to override.
-
- # GTM_H lists the config files that the generator files depend on,
-@@ -1186,6 +1217,7 @@
- SHLIB_NM_FLAGS='$(SHLIB_NM_FLAGS)' \
- MULTILIB_OSDIRNAMES='$(MULTILIB_OSDIRNAMES)' \
- mkinstalldirs='$(SHELL) $(srcdir)/mkinstalldirs' \
-+ LIBGCC_MULTI='$(LIBGCC_MULTI)' \
- $(SHELL) mklibgcc > tmp-libgcc.mk
- mv tmp-libgcc.mk libgcc.mk
-
-@@ -1351,7 +1383,9 @@
- sbitmap.o: sbitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) flags.h \
- hard-reg-set.h $(BASIC_BLOCK_H)
-
--COLLECT2_OBJS = collect2.o tlink.o intl.o version.o
-+### begin-GG-local: dynamic libraries
-+COLLECT2_OBJS = collect2.o tlink.o intl.o version.o $(EXTRA_COLLECT2_OBJS)
-+### end-GG-local
- COLLECT2_LIBS = @COLLECT2_LIBS@
- collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS)
- # Don't try modifying collect2 (aka ld) in place--it might be linking this.
-@@ -2641,7 +2675,7 @@
- #
- # Remake the info files.
-
--doc: $(BUILD_INFO) $(GENERATED_MANPAGES) gccbug
-+doc: $(BUILD_INFO) $(GENERATED_MANPAGES) gccbug $(EXTRA_DOC_TARGETS)
-
- INFOFILES = doc/cpp.info doc/gcc.info doc/gccint.info \
- doc/gccinstall.info doc/cppinternals.info
-@@ -2810,7 +2844,7 @@
- -rm -f config.h tconfig.h bconfig.h tm_p.h tm.h
- -rm -f cs-*
- -rm -rf libgcc
-- -rm -f doc/*.dvi
-+ -rm -f doc/*.dvi doc/*.guide
- # Delete the include directory.
- -rm -rf include
- # Delete files used by the "multilib" facility (including libgcc subdirs).
-@@ -2870,7 +2904,7 @@
- # broken is small.
- install: install-common $(INSTALL_HEADERS) $(INSTALL_LIBGCC) \
- install-cpp install-man install-info install-@POSUB@ \
-- lang.install-normal install-driver
-+ $(EXTRA_INSTALL_TARGETS) lang.install-normal install-driver
-
- # Handle cpp installation.
- install-cpp: cpp$(exeext)
-@@ -3647,7 +3681,7 @@
- cp stage1/$${f} . ; \
- else true; \
- fi; done
--stage1: force stage1-start lang.stage1
-+stage1: force stage1-start lang.stage1 $(EXTRA_STAGE1_TARGETS)
- -for dir in . $(SUBDIRS) ; \
- do \
- rm -f $$dir/*$(coverageexts) ; \
-@@ -3684,7 +3718,7 @@
- cp stage2/$${f} . ; \
- else true; \
- fi; done
--stage2: force stage2-start lang.stage2
-+stage2: force stage2-start lang.stage2 $(EXTRA_STAGE2_TARGETS)
-
- stage3-start:
- -if [ -d stage3 ] ; then true ; else mkdir stage3 ; fi
-@@ -3717,7 +3751,7 @@
- cp stage3/$${f} . ; \
- else true; \
- fi; done
--stage3: force stage3-start lang.stage3
-+stage3: force stage3-start lang.stage3 $(EXTRA_STAGE3_TARGETS)
-
- stage4-start:
- -if [ -d stage4 ] ; then true ; else mkdir stage4 ; fi
-@@ -3750,7 +3784,7 @@
- cp stage4/$${f} . ; \
- else true; \
- fi; done
--stage4: force stage4-start lang.stage4
-+stage4: force stage4-start lang.stage4 $(EXTRA_STAGE4_TARGETS)
-
- stageprofile-start:
- -if [ -d stageprofile ] ; then true ; else mkdir stageprofile ; fi
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.c-decl.c.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.c-decl.c.p
deleted file mode 100644
index 6e7e353..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.c-decl.c.p
+++ /dev/null
@@ -1,87 +0,0 @@
---- gcc-3.4.6/gcc/c-decl.c 2013-05-19 20:09:27.000000000 +0200
-+++ gcc/c-decl.c 2013-05-19 20:23:32.000000000 +0200
-@@ -2960,7 +2960,7 @@
- and push that on the current scope. */
-
- void
--push_parm_decl (tree parm)
-+push_parm_decl (tree parm, tree asmspec)
- {
- tree decl;
- int old_dont_save_pending_sizes_p = 0;
-@@ -2983,6 +2983,75 @@
- PARM, 0, NULL);
- decl_attributes (&decl, TREE_VALUE (parm), 0);
-
-+ /* begin-GG-local: explicit register specification for parameters */
-+ if (asmspec)
-+#ifdef TARGET_AMIGAOS
-+ {
-+ const char *regname=TREE_STRING_POINTER(asmspec);
-+ int regnum;
-+ if ((regnum=decode_reg_name(regname))>=0)
-+ {
-+ tree type=TREE_TYPE(decl);
-+ if (HARD_REGNO_MODE_OK(regnum, TYPE_MODE(type)))
-+ {
-+ tree t, attrs;
-+ /* Build tree for __attribute__ ((asm(regnum))). */
-+#if 0
-+ /* This doesn't work well because of a bug in
-+ attribute_list_contained(), which passes list of arguments to
-+ simple_cst_equal() instead of passing every argument
-+ separately. */
-+ attrs=tree_cons(get_identifier("asm"), tree_cons(NULL_TREE,
-+ build_int_2_wide(regnum, 0), NULL_TREE), NULL_TREE);
-+#else
-+ attrs=tree_cons(get_identifier("asm"),
-+ build_int_2_wide(regnum, 0), NULL_TREE);
-+#endif
-+#if 0
-+ /* build_type_attribute_variant() would seem to be more
-+ appropriate here. However, that function does not support
-+ attributes for parameters properly. It modifies
-+ TYPE_MAIN_VARIANT of a new type. As a result, comptypes()
-+ thinks that types of parameters in prototype and definition
-+ are different and issues error messages. See also comment
-+ below. */
-+ type=build_type_attribute_variant(type, attrs);
-+#else
-+ /* First check whether such a type already exists - if yes, use
-+ that one. This is very important, since otherwise
-+ common_type() would think that it sees two different
-+ types and would try to merge them - this could result in
-+ warning messages. */
-+ for (t=TYPE_MAIN_VARIANT(type); t; t=TYPE_NEXT_VARIANT(t))
-+ if (comptypes(t, type, COMPARE_STRICT)==1
-+ && attribute_list_equal(TYPE_ATTRIBUTES(t), attrs))
-+ break;
-+ if (t)
-+ type=t;
-+ else
-+ {
-+ /* Create a new variant, with differing attributes.
-+ (Hack! Type with differing attributes should no longer be
-+ a variant of its main type. See comment above for
-+ explanation why this was necessary). */
-+ type=build_type_copy(type);
-+ TYPE_ATTRIBUTES(type)=attrs;
-+ }
-+#endif
-+ TREE_TYPE(decl)=type;
-+ }
-+ else
-+ error ("%Jregister specified for '%D' isn't suitable for data type",
-+ decl, decl);
-+ }
-+ else
-+ error ("invalid register name `%s'", regname);
-+ }
-+#else /* !TARGET_AMIGAOS */
-+ error("explicit register specification for parameters is not supported for this target");
-+#endif /* !TARGET_AMIGAOS */
-+ /* end-GG-local */
-+
- decl = pushdecl (decl);
-
- finish_decl (decl, NULL_TREE, NULL_TREE);
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.c-incpath.c.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.c-incpath.c.p
deleted file mode 100644
index 9e91ea1..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.c-incpath.c.p
+++ /dev/null
@@ -1,19 +0,0 @@
---- gcc-3.4.6/gcc/c-incpath.c 2013-05-19 19:56:46.000000000 +0200
-+++ gcc/c-incpath.c 2013-05-19 20:23:32.000000000 +0200
-@@ -28,14 +28,14 @@
- #include "c-incpath.h"
- #include "cppdefault.h"
-
--/* Windows does not natively support inodes, and neither does MSDOS.
-+/* Windows does not natively support inodes, and neither does MSDOS or AmigaOS.
- Cygwin's emulation can generate non-unique inodes, so don't use it.
- VMS has non-numeric inodes. */
- #ifdef VMS
- # define INO_T_EQ(A, B) (!memcmp (&(A), &(B), sizeof (A)))
- # define INO_T_COPY(DEST, SRC) memcpy(&(DEST), &(SRC), sizeof (SRC))
- #else
--# if (defined _WIN32 && ! defined (_UWIN)) || defined __MSDOS__
-+# if (defined _WIN32 && ! defined (_UWIN)) || defined __MSDOS__ || __amigaos__
- # define INO_T_EQ(A, B) 0
- # else
- # define INO_T_EQ(A, B) ((A) == (B))
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.c-parse.in.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.c-parse.in.p
deleted file mode 100644
index bedb438..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.c-parse.in.p
+++ /dev/null
@@ -1,223 +0,0 @@
---- c-parse.in 2004-10-15 00:12:53.000000000 +0100
-+++ gcc/c-parse.in 2015-01-01 13:56:51.039003490 +0000
-@@ -29,7 +29,7 @@ Software Foundation, 59 Temple Place - S
- written by AT&T, but I have never seen it. */
-
- @@ifc
--%expect 10 /* shift/reduce conflicts, and no reduce/reduce conflicts. */
-+%expect 11 /* shift/reduce conflicts, and no reduce/reduce conflicts. */
- @@end_ifc
-
- %{
-@@ -1730,7 +1730,7 @@ enum_head:
-
- structsp_attr:
- struct_head identifier '{'
-- { $$ = start_struct (RECORD_TYPE, $2);
-+ { $<ttype>$ = start_struct (RECORD_TYPE, $2);
- /* Start scope of tag before parsing components. */
- }
- component_decl_list '}' maybe_attribute
-@@ -1741,7 +1741,7 @@ structsp_attr:
- nreverse ($3), chainon ($1, $5));
- }
- | union_head identifier '{'
-- { $$ = start_struct (UNION_TYPE, $2); }
-+ { $<ttype>$ = start_struct (UNION_TYPE, $2); }
- component_decl_list '}' maybe_attribute
- { $$ = finish_struct ($<ttype>4, nreverse ($5),
- chainon ($1, $7)); }
-@@ -1750,12 +1750,12 @@ structsp_attr:
- nreverse ($3), chainon ($1, $5));
- }
- | enum_head identifier '{'
-- { $$ = start_enum ($2); }
-+ { $<ttype>$ = start_enum ($2); }
- enumlist maybecomma_warn '}' maybe_attribute
- { $$ = finish_enum ($<ttype>4, nreverse ($5),
- chainon ($1, $8)); }
- | enum_head '{'
-- { $$ = start_enum (NULL_TREE); }
-+ { $<ttype>$ = start_enum (NULL_TREE); }
- enumlist maybecomma_warn '}' maybe_attribute
- { $$ = finish_enum ($<ttype>3, nreverse ($4),
- chainon ($1, $7)); }
-@@ -1927,20 +1927,25 @@ absdcl: /* an absolute declarator */
- | absdcl1
- ;
-
-+/* begin-GG-local: explicit register specification for parameters */
- absdcl_maybe_attribute: /* absdcl maybe_attribute, but not just attributes */
-- /* empty */
-- { $$ = build_tree_list (build_tree_list (current_declspecs,
-- NULL_TREE),
-- all_prefix_attributes); }
-- | absdcl1
-- { $$ = build_tree_list (build_tree_list (current_declspecs,
-- $1),
-- all_prefix_attributes); }
-- | absdcl1_noea attributes
-- { $$ = build_tree_list (build_tree_list (current_declspecs,
-- $1),
-- chainon ($2, all_prefix_attributes)); }
-+ maybeasm
-+ { $$ = build_tree_list (
-+ build_tree_list (build_tree_list (current_declspecs, NULL_TREE),
-+ all_prefix_attributes),
-+ $1); }
-+ | absdcl1 maybeasm
-+ { $$ = build_tree_list (
-+ build_tree_list (build_tree_list (current_declspecs, $1),
-+ all_prefix_attributes),
-+ $2); }
-+ | absdcl1_noea maybeasm attributes
-+ { $$ = build_tree_list (
-+ build_tree_list (build_tree_list (current_declspecs, $1),
-+ chainon ($3, all_prefix_attributes)),
-+ $2); }
- ;
-+/* end-GG-local */
-
- absdcl1: /* a nonempty absolute declarator */
- absdcl1_ea
-@@ -2596,33 +2601,37 @@ parmlist_2: /* empty */
- }
- ;
-
-+/* begin-GG-local: explicit register specification for parameters */
- parms:
- firstparm
-- { push_parm_decl ($1); }
-+ { push_parm_decl (TREE_PURPOSE($1), TREE_VALUE($1)); }
- | parms ',' parm
-- { push_parm_decl ($3); }
-+ { push_parm_decl (TREE_PURPOSE($3), TREE_VALUE($3)); }
- ;
-
- /* A single parameter declaration or parameter type name,
- as found in a parmlist. */
- parm:
-- declspecs_ts setspecs parm_declarator maybe_attribute
-- { $$ = build_tree_list (build_tree_list (current_declspecs,
-- $3),
-- chainon ($4, all_prefix_attributes));
-+ declspecs_ts setspecs parm_declarator maybeasm maybe_attribute
-+ { $$ = build_tree_list (
-+ build_tree_list (build_tree_list (current_declspecs, $3),
-+ chainon ($5, all_prefix_attributes)),
-+ $4);
- POP_DECLSPEC_STACK; }
-- | declspecs_ts setspecs notype_declarator maybe_attribute
-- { $$ = build_tree_list (build_tree_list (current_declspecs,
-- $3),
-- chainon ($4, all_prefix_attributes));
-+ | declspecs_ts setspecs notype_declarator maybeasm maybe_attribute
-+ { $$ = build_tree_list (
-+ build_tree_list (build_tree_list (current_declspecs, $3),
-+ chainon ($5, all_prefix_attributes)),
-+ $4);
- POP_DECLSPEC_STACK; }
- | declspecs_ts setspecs absdcl_maybe_attribute
- { $$ = $3;
- POP_DECLSPEC_STACK; }
-- | declspecs_nots setspecs notype_declarator maybe_attribute
-- { $$ = build_tree_list (build_tree_list (current_declspecs,
-- $3),
-- chainon ($4, all_prefix_attributes));
-+ | declspecs_nots setspecs notype_declarator maybeasm maybe_attribute
-+ { $$ = build_tree_list (
-+ build_tree_list (build_tree_list (current_declspecs, $3),
-+ chainon ($5, all_prefix_attributes)),
-+ $4);
- POP_DECLSPEC_STACK; }
-
- | declspecs_nots setspecs absdcl_maybe_attribute
-@@ -2633,29 +2642,33 @@ parm:
- /* The first parm, which must suck attributes from off the top of the parser
- stack. */
- firstparm:
-- declspecs_ts_nosa setspecs_fp parm_declarator maybe_attribute
-- { $$ = build_tree_list (build_tree_list (current_declspecs,
-- $3),
-- chainon ($4, all_prefix_attributes));
-+ declspecs_ts_nosa setspecs_fp parm_declarator maybeasm maybe_attribute
-+ { $$ = build_tree_list (
-+ build_tree_list (build_tree_list (current_declspecs, $3),
-+ chainon ($5, all_prefix_attributes)),
-+ $4);
- POP_DECLSPEC_STACK; }
-- | declspecs_ts_nosa setspecs_fp notype_declarator maybe_attribute
-- { $$ = build_tree_list (build_tree_list (current_declspecs,
-- $3),
-- chainon ($4, all_prefix_attributes));
-+ | declspecs_ts_nosa setspecs_fp notype_declarator maybeasm maybe_attribute
-+ { $$ = build_tree_list (
-+ build_tree_list (build_tree_list (current_declspecs, $3),
-+ chainon ($5, all_prefix_attributes)),
-+ $4);
- POP_DECLSPEC_STACK; }
- | declspecs_ts_nosa setspecs_fp absdcl_maybe_attribute
- { $$ = $3;
- POP_DECLSPEC_STACK; }
-- | declspecs_nots_nosa setspecs_fp notype_declarator maybe_attribute
-- { $$ = build_tree_list (build_tree_list (current_declspecs,
-- $3),
-- chainon ($4, all_prefix_attributes));
-+ | declspecs_nots_nosa setspecs_fp notype_declarator maybeasm maybe_attribute
-+ { $$ = build_tree_list (
-+ build_tree_list (build_tree_list (current_declspecs, $3),
-+ chainon ($5, all_prefix_attributes)),
-+ $4);
- POP_DECLSPEC_STACK; }
-
- | declspecs_nots_nosa setspecs_fp absdcl_maybe_attribute
- { $$ = $3;
- POP_DECLSPEC_STACK; }
- ;
-+/* end-GG-local */
-
- setspecs_fp:
- setspecs
-@@ -3055,28 +3068,32 @@ mydecl:
- { pedwarn ("empty declaration"); }
- ;
-
-+/* begin-GG-local: explicit register specification for parameters */
- myparms:
- myparm
-- { push_parm_decl ($1); }
-+ { push_parm_decl (TREE_PURPOSE($1), TREE_VALUE($1)); }
- | myparms ',' myparm
-- { push_parm_decl ($3); }
-+ { push_parm_decl (TREE_PURPOSE($3), TREE_VALUE($3)); }
- ;
-
- /* A single parameter declaration or parameter type name,
- as found in a parmlist. DOES NOT ALLOW AN INITIALIZER OR ASMSPEC */
-
- myparm:
-- parm_declarator maybe_attribute
-- { $$ = build_tree_list (build_tree_list (current_declspecs,
-- $1),
-- chainon ($2, all_prefix_attributes)); }
-- | notype_declarator maybe_attribute
-- { $$ = build_tree_list (build_tree_list (current_declspecs,
-- $1),
-- chainon ($2, all_prefix_attributes)); }
-+ parm_declarator maybeasm maybe_attribute
-+ { $$ = build_tree_list (
-+ build_tree_list (build_tree_list (current_declspecs, $1),
-+ chainon ($3, all_prefix_attributes)),
-+ $2); }
-+ | notype_declarator maybeasm maybe_attribute
-+ { $$ = build_tree_list (
-+ build_tree_list (build_tree_list (current_declspecs, $1),
-+ chainon ($2, all_prefix_attributes)),
-+ $2); }
- | absdcl_maybe_attribute
- { $$ = $1; }
- ;
-+/* end-GG-local */
-
- optparmlist:
- /* empty */
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.c-tree.h.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.c-tree.h.p
deleted file mode 100644
index 629c4ef..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.c-tree.h.p
+++ /dev/null
@@ -1,13 +0,0 @@
---- gcc-3.4.6/gcc/c-tree.h 2004-03-01 00:34:49.000000000 +0100
-+++ gcc/c-tree.h 2013-05-19 20:23:32.000000000 +0200
-@@ -214,7 +214,9 @@
- extern void pending_xref_error (void);
- extern void c_push_function_context (struct function *);
- extern void c_pop_function_context (struct function *);
--extern void push_parm_decl (tree);
-+/* begin-GG-local: explicit register specification for parameters */
-+extern void push_parm_decl (tree, tree);
-+/* end-GG-local */
- extern tree pushdecl_top_level (tree);
- extern void pushtag (tree, tree);
- extern tree set_array_declarator_type (tree, tree, int);
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.calls.c.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.calls.c.p
deleted file mode 100644
index b75a0f5..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.calls.c.p
+++ /dev/null
@@ -1,24 +0,0 @@
---- gcc-3.4.6/gcc/calls.c 2013-05-19 20:08:05.000000000 +0200
-+++ gcc/calls.c 2013-05-19 20:23:32.000000000 +0200
-@@ -3777,6 +3777,10 @@
- }
- fun = orgfun;
-
-+#ifdef LIBCALL_ENCODE_SECTION_INFO
-+ LIBCALL_ENCODE_SECTION_INFO (fun);
-+#endif
-+
- /* Ensure current function's preferred stack boundary is at least
- what we need. */
- if (cfun->preferred_stack_boundary < PREFERRED_STACK_BOUNDARY)
-@@ -3812,6 +3816,10 @@
-
- /* ??? Unfinished: must pass the memory address as an argument. */
-
-+#ifdef LIBCALL_ENCODE_SECTION_INFO
-+ LIBCALL_ENCODE_SECTION_INFO (fun);
-+#endif
-+
- /* Copy all the libcall-arguments out of the varargs data
- and into a vector ARGVEC.
-
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.collect2.c.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.collect2.c.p
deleted file mode 100644
index 519a71f..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.collect2.c.p
+++ /dev/null
@@ -1,200 +0,0 @@
---- gcc-3.4.6/gcc/collect2.c 2013-05-19 20:08:05.000000000 +0200
-+++ gcc/collect2.c 2013-05-19 20:23:32.000000000 +0200
-@@ -144,6 +144,12 @@
- #define SCAN_LIBRARIES
- #endif
-
-+/* begin-GG-local: dynamic libraries */
-+#ifndef DO_COLLECTING
-+#define DO_COLLECTING do_collecting
-+#endif
-+/* end-GG-local */
-+
- #ifdef USE_COLLECT2
- int do_collecting = 1;
- #else
-@@ -256,8 +262,10 @@
- static void prefix_from_env (const char *, struct path_prefix *);
- static void prefix_from_string (const char *, struct path_prefix *);
- static void do_wait (const char *);
--static void fork_execute (const char *, char **);
--static void maybe_unlink (const char *);
-+/* begin-GG-local: dynamic libraries */
-+void fork_execute (const char *, char **);
-+void maybe_unlink (const char *);
-+/* end-GG-local */
- static void add_to_list (struct head *, const char *);
- static int extract_init_priority (const char *);
- static void sort_ids (struct head *);
-@@ -335,6 +343,12 @@
- if (status != 0 && output_file != 0 && output_file[0])
- maybe_unlink (output_file);
-
-+/* begin-GG-local: dynamic libraries */
-+#ifdef COLLECT2_EXTRA_CLEANUP
-+ COLLECT2_EXTRA_CLEANUP();
-+#endif
-+/* end-GG-local */
-+
- exit (status);
- }
-
-@@ -423,6 +437,12 @@
- maybe_unlink (export_file);
- #endif
-
-+/* begin-GG-local: dynamic libraries */
-+#ifdef COLLECT2_EXTRA_CLEANUP
-+ COLLECT2_EXTRA_CLEANUP();
-+#endif
-+/* end-GG-local */
-+
- signal (signo, SIG_DFL);
- kill (getpid (), signo);
- }
-@@ -609,11 +629,7 @@
-
- /* Determine the filename to execute (special case for absolute paths). */
-
-- if (*name == '/'
--#ifdef HAVE_DOS_BASED_FILE_SYSTEM
-- || (*name && name[1] == ':')
--#endif
-- )
-+ if (IS_ABSOLUTE_PATH (name))
- {
- if (access (name, X_OK) == 0)
- {
-@@ -881,6 +897,11 @@
- const char *q = extract_string (&p);
- if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
- num_c_args++;
-+/* begin-GG-local: dynamic libraries */
-+#ifdef COLLECT2_GCC_OPTIONS_HOOK
-+ COLLECT2_GCC_OPTIONS_HOOK(q);
-+#endif
-+/* end-GG-local */
- }
- obstack_free (&temporary_obstack, temporary_firstobj);
-
-@@ -1112,6 +1133,11 @@
- add_to_list (&libs, s);
- }
- #endif
-+/* begin-GG-local: dynamic libraries */
-+#ifdef COLLECT2_LIBNAME_HOOK
-+ COLLECT2_LIBNAME_HOOK(arg);
-+#endif
-+/* end-GG-local */
- break;
-
- #ifdef COLLECT_EXPORT_LIST
-@@ -1146,7 +1172,9 @@
- break;
-
- case 's':
-- if (arg[2] == '\0' && do_collecting)
-+/* begin-GG-local: dynamic libraries */
-+ if (arg[2] == '\0' && DO_COLLECTING)
-+/* end-GG-local */
- {
- /* We must strip after the nm run, otherwise C++ linking
- will not work. Thus we strip in the second ld run, or
-@@ -1190,6 +1218,11 @@
- add_to_list (&libs, arg);
- }
- #endif
-+/* begin-GG-local: dynamic libraries */
-+#ifdef COLLECT2_LIBNAME_HOOK
-+ COLLECT2_LIBNAME_HOOK(arg);
-+#endif
-+/* end-GG-local */
- }
- }
-
-@@ -1283,6 +1316,12 @@
- fprintf (stderr, "\n");
- }
-
-+/* begin-GG-local: dynamic libraries */
-+#ifdef COLLECT2_PRELINK_HOOK
-+ COLLECT2_PRELINK_HOOK(ld1_argv, &strip_flag);
-+#endif
-+/* end-GG-local */
-+
- /* Load the program, searching all libraries and attempting to provide
- undefined symbols from repository information. */
-
-@@ -1295,7 +1334,9 @@
- constructor or destructor list, just return now. */
- if (rflag
- #ifndef COLLECT_EXPORT_LIST
-- || ! do_collecting
-+/* begin-GG-local: dynamic libraries */
-+ || ! DO_COLLECTING
-+/* end-GG-local */
- #endif
- )
- {
-@@ -1312,6 +1353,8 @@
- return 0;
- }
-
-+/* begin-GG-local: dynamic libraries */
-+#ifndef COLLECT2_POSTLINK_HOOK
- /* Examine the namelist with nm and search it for static constructors
- and destructors to call.
- Write the constructor and destructor tables to a .s file and reload. */
-@@ -1331,6 +1374,10 @@
- notice ("%d destructor(s) found\n", destructors.number);
- notice ("%d frame table(s) found\n", frame_tables.number);
- }
-+#else /* COLLECT2_POSTLINK_HOOK */
-+ COLLECT2_POSTLINK_HOOK(output_file);
-+#endif
-+/* end-GG-local */
-
- if (constructors.number == 0 && destructors.number == 0
- && frame_tables.number == 0
-@@ -1363,6 +1410,11 @@
- #endif
- maybe_unlink (c_file);
- maybe_unlink (o_file);
-+/* begin-GG-local: dynamic libraries */
-+#ifdef COLLECT2_EXTRA_CLEANUP
-+ COLLECT2_EXTRA_CLEANUP();
-+#endif
-+/* end-GG-local */
- return 0;
- }
-
-@@ -1454,6 +1506,11 @@
- maybe_unlink (export_file);
- #endif
-
-+/* begin-GG-local: dynamic libraries */
-+#ifdef COLLECT2_EXTRA_CLEANUP
-+ COLLECT2_EXTRA_CLEANUP();
-+#endif
-+/* end-GG-local */
- return 0;
- }
-
-@@ -1567,7 +1624,7 @@
- fatal_perror (errmsg_fmt, errmsg_arg);
- }
-
--static void
-+void
- fork_execute (const char *prog, char **argv)
- {
- collect_execute (prog, argv, NULL);
-@@ -1576,7 +1633,7 @@
-
- /* Unlink a file unless we are debugging. */
-
--static void
-+void
- maybe_unlink (const char *file)
- {
- if (!debug)
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.common.opt.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.common.opt.p
deleted file mode 100644
index 61050e1..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.common.opt.p
+++ /dev/null
@@ -1,17 +0,0 @@
---- gcc-3.4.6/gcc/common.opt 2013-05-19 20:02:45.000000000 +0200
-+++ gcc/common.opt 2013-05-19 20:23:32.000000000 +0200
-@@ -226,6 +226,14 @@
- Common
- Generate unwind tables that are exact at each instruction boundary
-
-+fbaserel
-+Common
-+Generate base-relative code
-+
-+fbaserel32
-+Common
-+Generate base-relative code with no data limits
-+
- fbounds-check
- Common
- Generate code to check bounds before indexing arrays
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.gcc.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.gcc.p
deleted file mode 100644
index 76465d5..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.gcc.p
+++ /dev/null
@@ -1,17 +0,0 @@
---- gcc-3.4.6/gcc/config.gcc 2013-05-19 20:09:27.000000000 +0200
-+++ gcc/config.gcc 2013-05-19 20:23:32.000000000 +0200
-@@ -1466,6 +1466,14 @@
- tm_defines="MOTOROLA USE_GAS"
- extra_parts="crtbegin.o crtend.o"
- ;;
-+m68k-*-amigaos*)
-+ tmake_file=m68k/t-amigaos
-+ tm_file="${tm_file} m68k/amigaos.h"
-+ tm_p_file="${tm_p_file} m68k/amigaos-protos.h"
-+ tm_defines="TARGET_AMIGAOS TARGET_DEFAULT=0" # 68000, no 68881, no bitfield ops
-+ extra_objs=amigaos.o
-+ gnu_ld=yes
-+ ;;
- mcore-*-elf)
- tm_file="dbxelf.h elfos.h svr4.h ${tm_file} mcore/mcore-elf.h"
- tmake_file=mcore/t-mcore
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.host-linux.c.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.host-linux.c.p
deleted file mode 100644
index c040f23..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.host-linux.c.p
+++ /dev/null
@@ -1,11 +0,0 @@
---- gcc-3.4.6/gcc/config/host-linux.c 2013-05-19 20:51:29.000000000 +0200
-+++ gcc/config/host-linux.c 2013-05-19 20:51:47.000000000 +0200
-@@ -189,7 +189,7 @@
-
- /* Try to make an anonymous private mmap at the desired location. */
- addr = mmap (base, size, PROT_READ | PROT_WRITE,
-- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-+ MAP_PRIVATE | MAP_ANON, -1, 0);
-
- if (addr != base)
- {
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.host.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.host.p
deleted file mode 100644
index 065fa66..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.host.p
+++ /dev/null
@@ -1,14 +0,0 @@
---- gcc-3.4.6/gcc/config.host 2013-05-19 20:09:27.000000000 +0200
-+++ gcc/config.host 2013-05-19 20:23:32.000000000 +0200
-@@ -154,6 +154,11 @@
- i860-*-sysv4*)
- host_xmake_file=i860/x-sysv4
- ;;
-+ m68k-*-amigaos*)
-+ host_xm_file=m68k/xm-amigaos.h
-+ host_xmake_file=m68k/x-amigaos
-+ out_host_hook_obj=host-amigaos.o
-+ ;;
- powerpc-*-darwin*)
- # powerpc-darwin host support.
- out_host_hook_obj=host-darwin.o
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.m68k.m68k-protos.h.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.m68k.m68k-protos.h.p
deleted file mode 100644
index 222d80c..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.m68k.m68k-protos.h.p
+++ /dev/null
@@ -1,14 +0,0 @@
---- gcc-3.4.6/gcc/config/m68k/m68k-protos.h 2013-05-19 20:09:27.000000000 +0200
-+++ gcc/config/m68k/m68k-protos.h 2013-05-19 20:23:32.000000000 +0200
-@@ -68,3 +68,11 @@
- extern void override_options (void);
- extern void init_68881_table (void);
- extern int m68k_hard_regno_rename_ok(unsigned int, unsigned int);
-+
-+#ifdef RTX_CODE
-+#ifdef TREE_CODE
-+extern void m68k_init_cumulative_args (CUMULATIVE_ARGS *, tree);
-+extern void m68k_function_arg_advance (CUMULATIVE_ARGS *);
-+extern struct rtx_def *m68k_function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree);
-+#endif
-+#endif
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.m68k.m68k.c.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.m68k.m68k.c.p
deleted file mode 100644
index 9ca42a1..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.m68k.m68k.c.p
+++ /dev/null
@@ -1,513 +0,0 @@
---- gcc-3.4.6/gcc/config/m68k/m68k.c 2013-05-19 20:09:27.000000000 +0200
-+++ gcc/config/m68k/m68k.c 2013-05-19 20:23:32.000000000 +0200
-@@ -123,6 +123,8 @@
- static tree m68k_handle_fndecl_attribute (tree *node, tree name,
- tree args, int flags,
- bool *no_add_attrs);
-+static tree m68k_handle_type_attribute (tree *, tree, tree, int, bool *);
-+static int m68k_comp_type_attributes (tree, tree);
- static void m68k_compute_frame_layout (void);
- static bool m68k_save_reg (unsigned int regno, bool interrupt_handler);
- static int const_int_cost (rtx);
-@@ -138,6 +140,8 @@
- const char *m68k_align_funcs_string;
- /* Specify the identification number of the library being built */
- const char *m68k_library_id_string;
-+/* Specify number of registers for integer, pointer and float arguments. */
-+const char *m68k_regparm_string;
-
- /* Specify power of two alignment used for loops. */
- int m68k_align_loops;
-@@ -145,6 +149,8 @@
- int m68k_align_jumps;
- /* Specify power of two alignment used for functions. */
- int m68k_align_funcs;
-+/* Specify number of registers for integer, pointer and float arguments. */
-+int m68k_regparm;
-
- /* Nonzero if the last compare/test insn had FP operands. The
- sCC expanders peek at this to determine what to do for the
-@@ -208,9 +214,30 @@
- {
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
- { "interrupt_handler", 0, 0, true, false, false, m68k_handle_fndecl_attribute },
-+
-+ /* Stkparm attribute specifies to pass arguments on the stack */
-+ { "stkparm", 0, 0, false, true, true, m68k_handle_type_attribute },
-+ /* Regparm attribute specifies how many integer arguments are to be
-+ passed in registers. */
-+ { "regparm", 0, 1, false, true, true, m68k_handle_type_attribute },
-+
-+#ifdef TARGET_AMIGAOS
-+ /* Stackext attribute specifies to generate stackextension code */
-+ { "stackext", 0, 0, false, true, true, amigaos_handle_type_attribute },
-+ /* Interrupt attribute specifies to generate a special exit code */
-+ { "interrupt", 0, 0, false, true, true, amigaos_handle_type_attribute },
-+ /* Saveds attribute specifies to generate baserel setup code */
-+ { "saveds", 0, 0, false, true, true, amigaos_handle_type_attribute },
-+ /* Chip attribute specifies to place data in a "special" section */
-+ { "chip", 0, 0, true, false, false, amigaos_handle_decl_attribute },
-+#endif
-+
- { NULL, 0, 0, false, false, false, NULL }
- };
-
-+#undef TARGET_COMP_TYPE_ATTRIBUTES
-+#define TARGET_COMP_TYPE_ATTRIBUTES m68k_comp_type_attributes
-+
- struct gcc_target targetm = TARGET_INITIALIZER;
-
- /* Sometimes certain combinations of command options do not make
-@@ -296,6 +323,23 @@
- m68k_align_funcs = i;
- }
-
-+ /* Validate -mregparm and -mregparm= value. */
-+ if (m68k_regparm_string)
-+ {
-+ m68k_regparm = atoi (m68k_regparm_string);
-+ if (m68k_regparm < 1 || m68k_regparm > M68K_MAX_REGPARM)
-+ error ("-mregparm=%d is not between 1 and %d",
-+ m68k_regparm, M68K_MAX_REGPARM);
-+ target_flags |= MASK_REGPARM;
-+ }
-+ else
-+ if (TARGET_REGPARM)
-+ m68k_regparm = M68K_DEFAULT_REGPARM;
-+
-+ /* XXX: FIXME: Workaround for a bug. */
-+ if (flag_pic >= 3)
-+ flag_strength_reduce = 0;
-+
- /* -fPIC uses 32-bit pc-relative displacements, which don't exist
- until the 68020. */
- if (!TARGET_68020 && !TARGET_COLDFIRE && (flag_pic == 2))
-@@ -312,12 +356,14 @@
- the PLT entry for `foo'. Doing function cse will cause the address of
- `foo' to be loaded into a register, which is exactly what we want to
- avoid when we are doing PIC on svr4 m68k. */
-- if (flag_pic)
-+ if (flag_pic && flag_pic < 3)
- flag_no_function_cse = 1;
-
- SUBTARGET_OVERRIDE_OPTIONS;
- }
-
-+/* Attributes support. */
-+
- /* Return nonzero if FUNC is an interrupt function as specified by the
- "interrupt_handler" attribute. */
- static bool
-@@ -350,6 +396,251 @@
- return NULL_TREE;
- }
-
-+/* Handle a "regparm" or "stkparm" attribute;
-+ arguments as in struct attribute_spec.handler. */
-+
-+static tree
-+m68k_handle_type_attribute (tree *node, tree name, tree args,
-+ int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
-+{
-+ if (TREE_CODE (*node) == FUNCTION_TYPE || TREE_CODE (*node) == METHOD_TYPE)
-+ {
-+ /* 'regparm' accepts one optional argument - number of registers in
-+ single class that should be used to pass arguments. */
-+ if (is_attribute_p ("regparm", name))
-+ {
-+ if (lookup_attribute ("stkparm", TYPE_ATTRIBUTES(*node)))
-+ {
-+ error ("`regparm' and `stkparm' are mutually exclusive");
-+ }
-+ if (args && TREE_CODE (args) == TREE_LIST)
-+ {
-+ tree numofregs = TREE_VALUE (args);
-+ if (numofregs)
-+ if (TREE_CODE (numofregs) != INTEGER_CST
-+/*
-+ || compare_tree_int(numofregs, 1) < 0
-+ || compare_tree_int(numofregs, M68K_MAX_REGPARM) > 0)
-+*/
-+ || TREE_INT_CST_HIGH (numofregs)
-+ || TREE_INT_CST_LOW (numofregs) < 1
-+ || TREE_INT_CST_LOW (numofregs) > M68K_MAX_REGPARM)
-+ {
-+ error ("invalid argument to `regparm' attribute");
-+ }
-+ }
-+ }
-+ else if (is_attribute_p ("stkparm", name))
-+ {
-+ if (lookup_attribute ("regparm", TYPE_ATTRIBUTES(*node)))
-+ {
-+ error ("`regparm' and `stkparm' are mutually exclusive");
-+ }
-+ }
-+ }
-+ else
-+ {
-+ warning ("`%s' attribute only applies to functions",
-+ IDENTIFIER_POINTER (name));
-+ *no_add_attrs = true;
-+ }
-+
-+ return NULL_TREE;
-+}
-+
-+/* Return zero if the attributes on TYPE1 and TYPE2 are incompatible,
-+ one if they are compatible, and two if they are nearly compatible
-+ (which causes a warning to be generated). */
-+
-+static int
-+m68k_comp_type_attributes (tree type1, tree type2)
-+{
-+ /* Functions or methods are incompatible if they specify mutually
-+ exclusive ways of passing arguments. */
-+ if (TREE_CODE (type1) == FUNCTION_TYPE || TREE_CODE (type1) == METHOD_TYPE)
-+ {
-+ tree arg1, arg2;
-+ if (!! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type1)) !=
-+ !! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type2))
-+ || !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1)) !=
-+ !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2)))
-+ return 0; /* 'regparm' and 'stkparm' are mutually exclusive. */
-+
-+ arg1 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1));
-+ arg2 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2));
-+ if (arg1 && arg2)
-+ {
-+ int num1 = 0, num2 = 0;
-+ if (TREE_VALUE (arg1) && TREE_CODE (TREE_VALUE (arg1)) == TREE_LIST)
-+ {
-+ tree numofregs = TREE_VALUE (TREE_VALUE (arg1));
-+ if (numofregs)
-+ num1 = TREE_INT_CST_LOW (numofregs);
-+ }
-+ if (TREE_VALUE (arg2) && TREE_CODE (TREE_VALUE (arg2)) == TREE_LIST)
-+ {
-+ tree numofregs = TREE_VALUE (TREE_VALUE (arg2));
-+ if (numofregs)
-+ num2 = TREE_INT_CST_LOW (numofregs);
-+ }
-+ if (num1 != num2)
-+ return 0; /* Different numbers, or no number in one type. */
-+ }
-+ }
-+#ifdef TARGET_AMIGAOS
-+ return amigaos_comp_type_attributes(type1, type2);
-+#else
-+ return 1;
-+#endif
-+}
-+
-+/* Argument-passing support functions. */
-+
-+/* Initialize a variable CUM of type CUMULATIVE_ARGS
-+ for a call to a function whose data type is FNTYPE.
-+ For a library call, FNTYPE is 0. */
-+
-+void
-+m68k_init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype)
-+{
-+ cum->last_arg_reg = -1;
-+ cum->regs_already_used = 0;
-+ if (fntype)
-+ {
-+ if (lookup_attribute ("stkparm", TYPE_ATTRIBUTES (fntype)))
-+ cum->num_of_regs = 0;
-+ else
-+ {
-+ tree ratree = lookup_attribute ("regparm", TYPE_ATTRIBUTES (fntype));
-+ if (ratree)
-+ {
-+ cum->num_of_regs = m68k_regparm ? m68k_regparm
-+ : M68K_DEFAULT_REGPARM;
-+ if (TREE_VALUE (ratree)
-+ && TREE_CODE (TREE_VALUE (ratree)) == TREE_LIST)
-+ {
-+ tree num_of_regs = TREE_VALUE (TREE_VALUE (ratree));
-+ cum->num_of_regs =
-+ num_of_regs ? TREE_INT_CST_LOW (num_of_regs) :
-+ (m68k_regparm ? m68k_regparm : M68K_DEFAULT_REGPARM);
-+ }
-+ }
-+ else
-+ cum->num_of_regs = m68k_regparm;
-+ }
-+ }
-+ else /* Libcall. */
-+ cum->num_of_regs = 0;
-+
-+ if (cum->num_of_regs)
-+ {
-+ /* If this is a vararg call, put all arguments on stack. */
-+ tree param, next_param;
-+ for (param = TYPE_ARG_TYPES (fntype); param; param = next_param)
-+ {
-+ next_param = TREE_CHAIN (param);
-+ if (!next_param && TREE_VALUE (param) != void_type_node)
-+ cum->num_of_regs = 0;
-+ }
-+ }
-+
-+#if ! defined (PCC_STATIC_STRUCT_RETURN) && defined (STRUCT_VALUE_REGNUM)
-+ /* If return value is a structure, and we pass the buffer address in a
-+ register, we can't use this register for our own purposes.
-+ FIXME: Something similar would be useful for static chain. */
-+ if (fntype && aggregate_value_p (TREE_TYPE (fntype), fntype))
-+ cum->regs_already_used |= (1 << STRUCT_VALUE_REGNUM);
-+#endif
-+}
-+
-+/* Update the data in CUM to advance over an argument. */
-+
-+void
-+m68k_function_arg_advance (CUMULATIVE_ARGS *cum)
-+{
-+ if (cum->last_arg_reg != -1)
-+ {
-+ int count;
-+ for (count = 0; count < cum->last_arg_len; count++)
-+ cum->regs_already_used |= (1 << (cum->last_arg_reg + count));
-+ cum->last_arg_reg = -1;
-+ }
-+}
-+
-+/* Define where to put the arguments to a function.
-+ Value is zero to push the argument on the stack,
-+ or a hard register in which to store the argument.
-+
-+ MODE is the argument's machine mode.
-+ TYPE is the data type of the argument (as a tree).
-+ This is null for libcalls where that information may
-+ not be available.
-+ CUM is a variable of type CUMULATIVE_ARGS which gives info about
-+ the preceding args and about the function being called. */
-+
-+struct rtx_def *
-+m68k_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type)
-+{
-+ if (cum->num_of_regs)
-+ {
-+ int regbegin = -1, altregbegin = -1, len;
-+
-+ /* FIXME: The last condition below is a workaround for a bug. */
-+ if (TARGET_68881 && FLOAT_MODE_P (mode) &&
-+ GET_MODE_UNIT_SIZE (mode) <= 12 &&
-+ (GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT || mode == SCmode))
-+ {
-+ regbegin = 16; /* FPx */
-+ len = GET_MODE_NUNITS (mode);
-+ }
-+ /* FIXME: Two last conditions below are workarounds for bugs. */
-+ else if (INTEGRAL_MODE_P (mode) && mode !=CQImode && mode != CHImode)
-+ {
-+ if (POINTER_TYPE_P (type))
-+ regbegin = 8; /* Ax */
-+ else
-+ regbegin = 0; /* Dx */
-+ altregbegin = 8 - regbegin;
-+ len = (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
-+ }
-+
-+ if (regbegin != -1)
-+ {
-+ int reg;
-+ long mask;
-+
-+look_for_reg:
-+ mask = 1 << regbegin;
-+ for (reg = 0; reg < cum->num_of_regs; reg++, mask <<= 1)
-+ if (!(cum->regs_already_used & mask))
-+ {
-+ int end;
-+ for (end = reg; end < cum->num_of_regs && end < reg + len;
-+ end++, mask <<= 1)
-+ if (cum->regs_already_used & mask)
-+ break;
-+ if (end == reg + len)
-+ {
-+ cum->last_arg_reg = reg + regbegin;
-+ cum->last_arg_len = len;
-+ break;
-+ }
-+ }
-+
-+ if (reg == cum->num_of_regs && altregbegin != -1)
-+ {
-+ regbegin = altregbegin;
-+ altregbegin = -1;
-+ goto look_for_reg;
-+ }
-+ }
-+
-+ if (cum->last_arg_reg != -1)
-+ return gen_rtx_REG (mode, cum->last_arg_reg);
-+ }
-+ return 0;
-+}
-+
- static void
- m68k_compute_frame_layout (void)
- {
-@@ -428,10 +719,14 @@
- static bool
- m68k_save_reg (unsigned int regno, bool interrupt_handler)
- {
-- if (flag_pic && current_function_uses_pic_offset_table
-+ if (flag_pic && flag_pic < 3 && current_function_uses_pic_offset_table
- && regno == PIC_OFFSET_TABLE_REGNUM)
- return true;
-
-+#ifdef EXTRA_SAVE_REG
-+ EXTRA_SAVE_REG(regno);
-+#endif
-+
- if (current_function_calls_eh_return)
- {
- unsigned int i;
-@@ -480,6 +775,9 @@
- m68k_output_function_prologue (FILE *stream, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
- {
- HOST_WIDE_INT fsize_with_regs;
-+#if !defined (DWARF2_DEBUGGING_INFO) && !defined (DWARF2_UNWIND_INFO)
-+#define dwarf2out_do_frame() 0
-+#endif
- HOST_WIDE_INT cfa_offset = INCOMING_FRAME_SP_OFFSET;
-
- m68k_compute_frame_layout();
-@@ -496,8 +794,17 @@
- if (TARGET_COLDFIRE && current_frame.reg_no > 2)
- fsize_with_regs += current_frame.reg_no * 4;
-
-+#ifdef PROLOGUE_BEGIN_HOOK
-+ PROLOGUE_BEGIN_HOOK (stream, fsize_with_regs);
-+#endif
-+
- if (frame_pointer_needed)
- {
-+#ifdef HAVE_ALTERNATE_FRAME_SETUP_F
-+ if (HAVE_ALTERNATE_FRAME_SETUP_F (fsize_with_regs))
-+ ALTERNATE_FRAME_SETUP_F (stream, fsize_with_regs);
-+ else
-+#endif
- if (current_frame.size == 0 && TARGET_68040)
- /* on the 68040, pea + move is faster than link.w 0 */
- fprintf (stream, MOTOROLA ?
-@@ -528,6 +835,10 @@
- cfa_offset += current_frame.size;
- }
- }
-+#ifdef HAVE_ALTERNATE_FRAME_SETUP
-+ else if (HAVE_ALTERNATE_FRAME_SETUP (fsize_with_regs))
-+ ALTERNATE_FRAME_SETUP (stream, fsize_with_regs);
-+#endif
- else if (fsize_with_regs) /* !frame_pointer_needed */
- {
- if (fsize_with_regs < 0x8000)
-@@ -658,7 +969,12 @@
- dwarf2out_reg_save (l, regno, -cfa_offset + n_regs++ * 4);
- }
- }
-- if (!TARGET_SEP_DATA && flag_pic &&
-+#ifdef HAVE_ALTERNATE_PIC_SETUP
-+ if (HAVE_ALTERNATE_PIC_SETUP)
-+ ALTERNATE_PIC_SETUP (stream);
-+ else
-+#endif
-+ if (!TARGET_SEP_DATA && flag_pic && flag_pic < 3 &&
- (current_function_uses_pic_offset_table ||
- (!current_function_is_leaf && TARGET_ID_SHARED_LIBRARY)))
- {
-@@ -921,6 +1237,11 @@
- }
- }
- if (frame_pointer_needed)
-+#ifdef HAVE_ALTERNATE_FRAME_DESTR_F
-+ if (HAVE_ALTERNATE_FRAME_DESTR_F (fsize_with_regs))
-+ ALTERNATE_FRAME_DESTR_F (stream, fsize_with_regs);
-+ else
-+#endif
- fprintf (stream, "\tunlk %s\n",
- reg_names[FRAME_POINTER_REGNUM]);
- else if (fsize_with_regs)
-@@ -958,10 +1279,17 @@
- }
- if (current_function_calls_eh_return)
- asm_fprintf (stream, "\tadd" ASM_DOT"l %Ra0,%Rsp\n");
-+#ifdef EPILOGUE_END_HOOK
-+ EPILOGUE_END_HOOK (stream);
-+#endif
- if (m68k_interrupt_function_p (current_function_decl))
- fprintf (stream, "\trte\n");
- else if (current_function_pops_args)
- asm_fprintf (stream, "\trtd %I%d\n", current_function_pops_args);
-+#ifdef HAVE_ALTERNATE_RETURN
-+ else if (HAVE_ALTERNATE_RETURN)
-+ ALTERNATE_RETURN (stream);
-+#endif
- else
- fprintf (stream, "\trts\n");
- }
-@@ -1454,12 +1782,20 @@
- /* First handle a simple SYMBOL_REF or LABEL_REF */
- if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
- {
-+#ifdef LEGITIMATE_BASEREL_OPERAND_P
-+ if (LEGITIMATE_BASEREL_OPERAND_P (orig))
-+ return orig;
-+#endif
-+
- if (reg == 0)
- abort ();
-
-- pic_ref = gen_rtx_MEM (Pmode,
-- gen_rtx_PLUS (Pmode,
-- pic_offset_table_rtx, orig));
-+ if (flag_pic < 3)
-+ pic_ref = gen_rtx_MEM (Pmode,
-+ gen_rtx_PLUS (Pmode,
-+ pic_offset_table_rtx, orig));
-+ else
-+ pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, orig);
- current_function_uses_pic_offset_table = 1;
- RTX_UNCHANGING_P (pic_ref) = 1;
- emit_move_insn (reg, pic_ref);
-@@ -3001,6 +3337,10 @@
- fprintf (file, ":w"); break;
- case 2:
- fprintf (file, ":l"); break;
-+ case 3:
-+ fprintf (file, ":W"); break;
-+ case 4:
-+ fprintf (file, ":L"); break;
- default:
- break;
- }
-@@ -3488,7 +3828,7 @@
- xops[0] = DECL_RTL (function);
-
- /* Logic taken from call patterns in m68k.md. */
-- if (flag_pic)
-+ if (flag_pic && flag_pic < 3)
- {
- if (TARGET_PCREL)
- fmt = "bra.l %o0";
-@@ -3544,7 +3884,8 @@
-
- /* Value is true if hard register REGNO can hold a value of machine-mode MODE.
- On the 68000, the cpu registers can hold any mode except bytes in address
-- registers, but the 68881 registers can hold only SFmode or DFmode. */
-+ registers, but the 68881 registers can hold only SFmode or DFmode.
-+ The 68881 registers can't hold anything if 68881 use is disabled. */
- bool
- m68k_regno_mode_ok (int regno, enum machine_mode mode)
- {
-@@ -3569,6 +3910,7 @@
- smaller. */
- if ((GET_MODE_CLASS (mode) == MODE_FLOAT
- || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
-+ && TARGET_68881
- && GET_MODE_UNIT_SIZE (mode) <= 12)
- return true;
- }
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.m68k.m68k.h.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.m68k.m68k.h.p
deleted file mode 100644
index b6d1f66..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.m68k.m68k.h.p
+++ /dev/null
@@ -1,175 +0,0 @@
---- gcc-3.4.6/gcc/config/m68k/m68k.h 2013-05-19 20:09:27.000000000 +0200
-+++ gcc/config/m68k/m68k.h 2013-05-19 20:23:32.000000000 +0200
-@@ -226,6 +226,11 @@
- #define MASK_ID_SHARED_LIBRARY (1<<18)
- #define TARGET_ID_SHARED_LIBRARY (target_flags & MASK_ID_SHARED_LIBRARY)
-
-+/* Compile using the first 'm68k_regparm' data, address and float
-+ registers for arguments passing. */
-+#define MASK_REGPARM (1<<24)
-+#define TARGET_REGPARM (target_flags & MASK_REGPARM)
-+
- /* Compile for a CPU32. A 68020 without bitfields is a good
- heuristic for a CPU32. */
- #define TARGET_CPU32 (TARGET_68020 && !TARGET_BITFIELD)
-@@ -342,6 +347,10 @@
- N_("Use different calling convention using 'rtd'") }, \
- { "nortd", - MASK_RTD, \
- N_("Use normal calling convention") }, \
-+ { "regparm", MASK_REGPARM, \
-+ N_("Pass arguments through registers") }, \
-+ { "no-regparm", - MASK_REGPARM, \
-+ N_("Don't pass arguments through registers") }, \
- SUBTARGET_SWITCHES \
- { "", TARGET_DEFAULT, "" }}
- /* TARGET_DEFAULT is defined in m68k-none.h, netbsd.h, etc. */
-@@ -364,6 +373,8 @@
- N_("Function starts are aligned to this power of 2"), 0}, \
- { "shared-library-id=", &m68k_library_id_string, \
- N_("ID of shared library to build"), 0}, \
-+ { "regparm=", &m68k_regparm_string, \
-+ N_("Use this register count to pass arguments"), 0}, \
- SUBTARGET_OPTIONS \
- }
-
-@@ -556,7 +567,8 @@
-
- /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
- On the 68000, the cpu registers can hold any mode except bytes in
-- address registers, the 68881 registers can hold only SFmode or DFmode. */
-+ address registers, the 68881 registers can hold only SFmode or DFmode.
-+ The 68881 registers can't hold anything if 68881 use is disabled. */
-
- #define HARD_REGNO_MODE_OK(REGNO, MODE) \
- m68k_regno_mode_ok ((REGNO), (MODE))
-@@ -805,7 +817,7 @@
- /* On the 68000, this is the size of MODE in words,
- except in the FP regs, where a single reg is always enough. */
- #define CLASS_MAX_NREGS(CLASS, MODE) \
-- ((CLASS) == FP_REGS ? 1 \
-+ ((CLASS) == FP_REGS ? GET_MODE_NUNITS (MODE) \
- : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
-
- /* Moves between fp regs and other regs are two insns. */
-@@ -901,10 +913,19 @@
-
- #define PCC_STATIC_STRUCT_RETURN
-
--/* 1 if N is a possible register number for function argument passing.
-- On the 68000, no registers are used in this way. */
-+/* 1 if N is a possible register number for function argument passing. */
-
--#define FUNCTION_ARG_REGNO_P(N) 0
-+#define FUNCTION_ARG_REGNO_P(N) \
-+ ((((int)N) >= 0 && (N) < M68K_MAX_REGPARM) \
-+ || ((N) >= 8 && (N) < 8 + M68K_MAX_REGPARM) \
-+ || (TARGET_68881 && (N) >= 16 && (N) < 16 + M68K_MAX_REGPARM))
-+
-+/* Nonzero if we need to generate special stack-allocating insns.
-+ On most systems they are not needed.
-+ When they are needed, also define ALTERNATE_ALLOCATE_STACK (see m68k.md)
-+ to perform the necessary actions. */
-+
-+#define TARGET_ALTERNATE_ALLOCATE_STACK 0
-
- /* Define a data type for recording info about an argument list
- during the scan of that argument list. This data type should
-@@ -912,28 +933,52 @@
- and about the args processed so far, enough to enable macros
- such as FUNCTION_ARG to determine where the next arg should go.
-
-- On the m68k, this is a single integer, which is a number of bytes
-- of arguments scanned so far. */
-+ On the m68k, this is a structure:
-+ num_of_regs: number of data, address and float registers to use for
-+ arguments passing (if it's 2, than pass arguments in d0, d1, a0, a1,
-+ fp0 and fp1). 0 - pass everything on stack. vararg calls are
-+ always passed entirely on stack.
-+ regs_already_used: bitmask of the already used registers.
-+ last_arg_reg - register number of the most recently passed argument.
-+ -1 if passed on stack.
-+ last_arg_len - number of registers used by the most recently passed
-+ argument.
-+*/
-
--#define CUMULATIVE_ARGS int
-+struct m68k_args
-+{
-+ int num_of_regs;
-+ long regs_already_used;
-+ int last_arg_reg;
-+ int last_arg_len;
-+};
-+
-+#define CUMULATIVE_ARGS struct m68k_args
-+
-+/* Max. number of data, address and float registers to be used for passing
-+ integer, pointer and float arguments when TARGET_REGPARM.
-+ It's 4, so d0-d3, a0-a3 and fp0-fp3 can be used. */
-+
-+#define M68K_MAX_REGPARM 4
-+
-+/* The default number of data, address and float registers to use when
-+ user specified '-mregparm' switch, not '-mregparm=<value>' option. */
-+
-+#define M68K_DEFAULT_REGPARM 2
-
- /* Initialize a variable CUM of type CUMULATIVE_ARGS
- for a call to a function whose data type is FNTYPE.
-- For a library call, FNTYPE is 0.
--
-- On the m68k, the offset starts at 0. */
-+ For a library call, FNTYPE is 0. */
-
- #define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
-- ((CUM) = 0)
-+ (m68k_init_cumulative_args (&(CUM), (FNTYPE)))
-
- /* Update the data in CUM to advance over an argument
- of mode MODE and data type TYPE.
- (TYPE is null for libcalls where that information may not be available.) */
-
- #define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
-- ((CUM) += ((MODE) != BLKmode \
-- ? (GET_MODE_SIZE (MODE) + 3) & ~3 \
-- : (int_size_in_bytes (TYPE) + 3) & ~3))
-+ (m68k_function_arg_advance (&(CUM)))
-
- /* Define where to put the arguments to a function.
- Value is zero to push the argument on the stack,
-@@ -948,9 +993,15 @@
- NAMED is nonzero if this argument is a named parameter
- (otherwise it is an extra parameter matching an ellipsis).
-
-- On the m68k all args are always pushed. */
-+ On m68k all args are pushed, except if -mregparm is specified, then
-+ a number of arguments is passed in the first 'm68k_regparm' data,
-+ address and float registers.
-+ Note: by default, the static-chain is passed in a0. Targets that want
-+ to make full use of '-mregparm' are advised to pass the static-chain
-+ somewhere else. */
-
--#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) 0
-+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
-+ (m68k_function_arg (&(CUM), (MODE), (TYPE)))
-
- /* For an arg passed partly in registers and partly in memory,
- this is the number of registers used.
-@@ -1688,14 +1739,17 @@
-
- #define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR)
-
-+
- /* Variables in m68k.c */
- extern const char *m68k_align_loops_string;
- extern const char *m68k_align_jumps_string;
- extern const char *m68k_align_funcs_string;
- extern const char *m68k_library_id_string;
-+extern const char *m68k_regparm_string;
- extern int m68k_align_loops;
- extern int m68k_align_jumps;
- extern int m68k_align_funcs;
-+extern int m68k_regparm;
- extern int m68k_last_compare_had_fp_operands;
-
-
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.m68k.m68k.md.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.m68k.m68k.md.p
deleted file mode 100644
index c63b8d5..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.m68k.m68k.md.p
+++ /dev/null
@@ -1,82 +0,0 @@
---- m68k.md.orig 2005-07-26 21:32:25.000000000 +0100
-+++ gcc/config/m68k/m68k.md 2015-01-01 14:46:17.666994805 +0000
-@@ -3679,7 +3679,7 @@
- target = operand_subword_force (operands[0], 0, SFmode);
- result = expand_binop (SImode, xor_optab,
- operand_subword_force (operands[1], 0, SFmode),
-- GEN_INT (0x80000000), target, 0, OPTAB_WIDEN);
-+ GEN_INT (-2147483647 - 1), target, 0, OPTAB_WIDEN);
- if (result == 0)
- abort ();
-
-@@ -3723,7 +3723,7 @@
- target = operand_subword (operands[0], 0, 1, DFmode);
- result = expand_binop (SImode, xor_optab,
- operand_subword_force (operands[1], 0, DFmode),
-- GEN_INT (0x80000000), target, 0, OPTAB_WIDEN);
-+ GEN_INT (-2147483647 - 1), target, 0, OPTAB_WIDEN);
- if (result == 0)
- abort ();
-
-@@ -6418,7 +6418,7 @@
- (match_operand:SI 1 "general_operand" "g"))]
- ;; Operand 1 not really used on the m68000.
-
-- "! flag_pic"
-+ "(! flag_pic || flag_pic >= 3)"
- {
- #if MOTOROLA && !defined (USE_GAS)
- return "jsr %0";
-@@ -6433,7 +6433,7 @@
- (match_operand:SI 1 "general_operand" "g"))]
- ;; Operand 1 not really used on the m68000.
-
-- "flag_pic"
-+ "(flag_pic && flag_pic < 3)"
- {
- m68k_output_pic_call(operands[0]);
- return "";
-@@ -6460,7 +6460,7 @@
- (call (match_operand:QI 1 "memory_operand" "o")
- (match_operand:SI 2 "general_operand" "g")))]
- ;; Operand 2 not really used on the m68000.
-- "! flag_pic"
-+ "(! flag_pic || flag_pic >= 3)"
- {
- #if MOTOROLA && !defined (USE_GAS)
- return "jsr %1";
-@@ -6475,7 +6475,7 @@
- (call (match_operand:QI 1 "memory_operand" "o")
- (match_operand:SI 2 "general_operand" "g")))]
- ;; Operand 2 not really used on the m68000.
-- "flag_pic"
-+ "(flag_pic && flag_pic < 3)"
- {
- m68k_output_pic_call(operands[1]);
- return "";
-@@ -7170,7 +7170,7 @@
- target = operand_subword (operands[0], 0, 1, XFmode);
- result = expand_binop (SImode, xor_optab,
- operand_subword_force (operands[1], 0, XFmode),
-- GEN_INT (0x80000000), target, 0, OPTAB_WIDEN);
-+ GEN_INT (-2147483647 - 1), target, 0, OPTAB_WIDEN);
- if (result == 0)
- abort ();
-
-@@ -7334,3 +7334,16 @@
- default: abort();
- }
- })
-+
-+; This is only needed for some subtargets.
-+(define_expand "allocate_stack"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (minus:SI (reg:SI 15) (match_operand:SI 1 "general_operand" "")))
-+ (set (reg:SI 15) (minus:SI (reg:SI 15) (match_dup 1)))]
-+ "TARGET_ALTERNATE_ALLOCATE_STACK"
-+ "
-+{
-+#ifdef ALTERNATE_ALLOCATE_STACK
-+ ALTERNATE_ALLOCATE_STACK(operands);
-+#endif
-+}")
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.configure.ac.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.configure.ac.p
deleted file mode 100644
index 728be6d..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.configure.ac.p
+++ /dev/null
@@ -1,35 +0,0 @@
---- gcc-3.4.6/gcc/configure.ac 2013-05-19 20:09:27.000000000 +0200
-+++ gcc/configure.ac 2013-05-19 20:23:32.000000000 +0200
-@@ -101,10 +101,11 @@
- # Directories
- # -----------
-
-+### begin-GG-local: local prefix
- # Specify the local prefix
- local_prefix=
- AC_ARG_WITH(local-prefix,
--[ --with-local-prefix=DIR specifies directory to put local include],
-+[ --with-local-prefix=DIR specifies directory to put local include directory (not files).],
- [case "${withval}" in
- yes) AC_MSG_ERROR(bad value ${withval} given for local include directory prefix) ;;
- no) ;;
-@@ -113,8 +114,9 @@
-
- # Default local prefix if it is empty
- if test x$local_prefix = x; then
-- local_prefix=/usr/local
-+ local_prefix='${prefix}'/local
- fi
-+### end-GG-local
-
- # Don't set gcc_gxx_include_dir to gxx_include_dir since that's only
- # passed in by the toplevel make and thus we'd get different behavior
-@@ -962,6 +964,8 @@
-
- gcc_AC_INITFINI_ARRAY
-
-+AC_FUNC_ALLOCA
-+
- # mkdir takes a single argument on some systems.
- gcc_AC_FUNC_MKDIR_TAKES_ONE_ARG
-
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.configure.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.configure.p
deleted file mode 100644
index d8ba1cf..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.configure.p
+++ /dev/null
@@ -1,61 +0,0 @@
---- gcc-3.4.6/gcc/configure 2013-05-19 20:09:27.000000000 +0200
-+++ gcc/configure 2013-05-19 20:23:32.000000000 +0200
-@@ -1583,6 +1583,7 @@
- # Directories
- # -----------
-
-+### begin-GG-local: local prefix
- # Specify the local prefix
- local_prefix=
-
-@@ -1600,8 +1601,9 @@
-
- # Default local prefix if it is empty
- if test x$local_prefix = x; then
-- local_prefix=/usr/local
-+ local_prefix='${prefix}'/local
- fi
-+### end-GG-local
-
- # Don't set gcc_gxx_include_dir to gxx_include_dir since that's only
- # passed in by the toplevel make and thus we'd get different behavior
-@@ -7258,7 +7260,7 @@
- # read() to the same fd. The only system known to have a problem here
- # is VMS, where text files have record structure.
- case "$host_os" in
-- vms* | ultrix*)
-+ vms* | ultrix* | amigaos*)
- gcc_cv_func_mmap_file=no ;;
- *)
- gcc_cv_func_mmap_file=yes;;
-@@ -7282,7 +7284,7 @@
- # Systems known to be in this category are Windows (all variants),
- # VMS, and Darwin.
- case "$host_os" in
-- vms* | cygwin* | pe | mingw* | darwin* | ultrix* | hpux10* | hpux11.00)
-+ vms* | cygwin* | pe | mingw* | darwin* | ultrix* | hpux10* | hpux11.00 | amigaos*)
- gcc_cv_func_mmap_dev_zero=no ;;
- *)
- gcc_cv_func_mmap_dev_zero=yes;;
-@@ -7367,7 +7369,7 @@
- # above for use of /dev/zero.
- # Systems known to be in this category are Windows, VMS, and SCO Unix.
- case "$host_os" in
-- vms* | cygwin* | pe | mingw* | sco* | udk* )
-+ vms* | cygwin* | pe | mingw* | sco* | udk* | amigaos*)
- gcc_cv_func_mmap_anon=no ;;
- *)
- gcc_cv_func_mmap_anon=yes;;
-@@ -7762,6 +7764,12 @@
-
- sparc_address_test (0);
-
-+#ifdef __amigaos__
-+ /* Force this test to succeed for AmigaOS, which has a fairly good
-+ vfork() emulation, but doesn't support fork() at all. -fnf */
-+ exit (0);
-+#endif
-+
- child = vfork ();
-
- if (child == 0) {
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.cppfiles.c.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.cppfiles.c.p
deleted file mode 100644
index 6457748..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.cppfiles.c.p
+++ /dev/null
@@ -1,48 +0,0 @@
---- gcc-3.4.6/gcc/cppfiles.c 2013-05-19 20:22:04.000000000 +0200
-+++ gcc/cppfiles.c 2013-05-19 20:23:32.000000000 +0200
-@@ -50,6 +50,10 @@
- #ifndef O_BINARY
- # define O_BINARY 0
- #endif
-+#ifndef OPEN_CASE_SENSITIVE
-+/* Default is standard open(). */
-+# define OPEN_CASE_SENSITIVE open
-+#endif
-
- /* This structure represents a file searched for by CPP, whether it
- exists or not. An instance may be pointed to by more than one
-@@ -210,7 +214,7 @@
- set_stdin_to_binary_mode ();
- }
- else
-- file->fd = open (file->path, O_RDONLY | O_NOCTTY | O_BINARY, 0666);
-+ file->fd = OPEN_CASE_SENSITIVE (file->path, O_RDONLY | O_NOCTTY | O_BINARY, 0666);
-
- if (file->fd != -1)
- {
-@@ -1109,7 +1113,11 @@
- flen = strlen (fname);
- path = xmalloc (dlen + 1 + flen + 1);
- memcpy (path, dir->name, dlen);
-- if (dlen && path[dlen - 1] != '/')
-+ if (dlen
-+#ifdef VOL_SEPARATOR
-+ && path[dlen - 1] != VOL_SEPARATOR
-+#endif
-+ && path[dlen - 1] != '/')
- path[dlen++] = '/';
- memcpy (&path[dlen], fname, flen + 1);
-
-@@ -1157,7 +1165,11 @@
- len = dir->len;
- name = alloca (len + sizeof (FILE_NAME_MAP_FILE) + 1);
- memcpy (name, dir->name, len);
-- if (len && name[len - 1] != '/')
-+ if (len
-+#ifdef VOL_SEPARATOR
-+ && name[len - 1] != VOL_SEPARATOR
-+#endif
-+ && name[len - 1] != '/')
- name[len++] = '/';
- strcpy (name + len, FILE_NAME_MAP_FILE);
- f = fopen (name, "r");
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.defaults.h.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.defaults.h.p
deleted file mode 100644
index 016e899..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.defaults.h.p
+++ /dev/null
@@ -1,13 +0,0 @@
---- gcc-3.4.6/gcc/defaults.h 2013-05-19 20:08:05.000000000 +0200
-+++ gcc/defaults.h 2013-05-19 20:23:32.000000000 +0200
-@@ -280,8 +280,10 @@
- /* If we have a definition of INCOMING_RETURN_ADDR_RTX, assume that
- the rest of the DWARF 2 frame unwind support is also provided. */
- #if !defined (DWARF2_UNWIND_INFO) && defined (INCOMING_RETURN_ADDR_RTX)
-+#if !defined (NO_DWARF2_UNWIND_INFO)
- #define DWARF2_UNWIND_INFO 1
- #endif
-+#endif
-
- /* If we have named sections, and we're using crtstuff to run ctors,
- use them for registering eh frame information. */
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.fixinc.mkfixinc.sh.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.fixinc.mkfixinc.sh.p
deleted file mode 100644
index 9024640..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.fixinc.mkfixinc.sh.p
+++ /dev/null
@@ -1,10 +0,0 @@
---- gcc-3.4.6/gcc/fixinc/mkfixinc.sh 2003-10-24 19:47:51.000000000 +0200
-+++ gcc/fixinc/mkfixinc.sh 2013-05-19 20:23:32.000000000 +0200
-@@ -47,6 +47,7 @@
- i?86-*-mingw32* | \
- i?86-*-uwin* | \
- i?86-*-interix* | \
-+ m68k-*-amigaos* | \
- powerpc-*-eabiaix* | \
- powerpc-*-eabisim* | \
- powerpc-*-eabi* | \
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.flow.c.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.flow.c.p
deleted file mode 100644
index 2934804..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.flow.c.p
+++ /dev/null
@@ -1,19 +0,0 @@
---- gcc-3.4.6/gcc/flow.c 2013-05-19 20:09:27.000000000 +0200
-+++ gcc/flow.c 2013-05-19 20:23:32.000000000 +0200
-@@ -2335,11 +2335,13 @@
- if (n_basic_blocks == 0
- || (regno < FIRST_PSEUDO_REGISTER
- && (global_regs[regno]
-- || fixed_regs[regno]
-- || FUNCTION_ARG_REGNO_P (regno))))
-+/* begin-GG-local: explicit register specification for parameters */
-+ || fixed_regs[regno])))
- return 0;
-
-- return REGNO_REG_SET_P (ENTRY_BLOCK_PTR->global_live_at_end, regno);
-+ return (REGNO_REG_SET_P (ENTRY_BLOCK_PTR->global_live_at_end, regno)
-+ && (regno >= FIRST_PSEUDO_REGISTER || ! function_arg_regno_p (regno)));
-+/* end-GG-local */
- }
-
- /* 1 if register REGNO was alive at a place where `setjmp' was called
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.function.c.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.function.c.p
deleted file mode 100644
index 299ea70..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.function.c.p
+++ /dev/null
@@ -1,31 +0,0 @@
---- gcc-3.4.6/gcc/function.c 2013-05-19 20:08:05.000000000 +0200
-+++ gcc/function.c 2013-05-19 20:23:32.000000000 +0200
-@@ -8153,3 +8153,28 @@
- }
-
- #include "gt-function.h"
-+
-+/* begin-GG-local: explicit register specification for parameters */
-+/* Return 1 if an argument for the current function was passed in
-+ register REGNO. */
-+
-+int
-+function_arg_regno_p (int regno)
-+{
-+ tree parm = DECL_ARGUMENTS (current_function_decl);
-+ for (; parm; parm = TREE_CHAIN (parm))
-+ {
-+ rtx incoming = DECL_INCOMING_RTL (parm);
-+ if (GET_CODE (incoming) == REG)
-+ {
-+ int incoming_reg;
-+ incoming_reg = REGNO (incoming);
-+ if (regno >= incoming_reg &&
-+ regno < incoming_reg + HARD_REGNO_NREGS (incoming_reg,
-+ GET_MODE (incoming)))
-+ return 1;
-+ }
-+ }
-+ return 0;
-+}
-+/* end-GG-local */
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.function.h.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.function.h.p
deleted file mode 100644
index 7752b0e..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.function.h.p
+++ /dev/null
@@ -1,11 +0,0 @@
---- gcc-3.4.6/gcc/function.h 2013-05-19 19:56:54.000000000 +0200
-+++ gcc/function.h 2013-05-19 20:23:32.000000000 +0200
-@@ -643,4 +643,8 @@
-
- extern void do_warn_unused_parameter (tree);
-
-+/* begin-GG-local: explicit register specification for parameters */
-+extern int function_arg_regno_p (int);
-+/* end-GG-local */
-+
- #endif /* GCC_FUNCTION_H */
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.gcc.c.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.gcc.c.p
deleted file mode 100644
index 4399b19..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.gcc.c.p
+++ /dev/null
@@ -1,63 +0,0 @@
---- gcc-3.4.6/gcc/gcc.c 2013-05-19 20:22:04.000000000 +0200
-+++ gcc/gcc.c 2013-05-19 20:23:32.000000000 +0200
-@@ -1403,16 +1403,29 @@
- #define MD_STARTFILE_PREFIX_1 ""
- #endif
-
-+#ifndef STANDARD_EXEC_PREFIX_1
-+#define STANDARD_EXEC_PREFIX_1 "/usr/libexec/gcc/"
-+#endif
-+#ifndef STANDARD_EXEC_PREFIX_2
-+#define STANDARD_EXEC_PREFIX_2 "/usr/lib/gcc/"
-+#endif
-+#ifndef STANDARD_STARTFILE_PREFIX_1
-+#define STANDARD_STARTFILE_PREFIX_1 "/lib/"
-+#endif
-+#ifndef STANDARD_STARTFILE_PREFIX_2
-+#define STANDARD_STARTFILE_PREFIX_2 "/usr/lib/"
-+#endif
-+
- static const char *const standard_exec_prefix = STANDARD_EXEC_PREFIX;
--static const char *const standard_exec_prefix_1 = "/usr/libexec/gcc/";
--static const char *const standard_exec_prefix_2 = "/usr/lib/gcc/";
-+static const char *const standard_exec_prefix_1 = STANDARD_EXEC_PREFIX_1;
-+static const char *const standard_exec_prefix_2 = STANDARD_EXEC_PREFIX_2;
- static const char *md_exec_prefix = MD_EXEC_PREFIX;
-
- static const char *md_startfile_prefix = MD_STARTFILE_PREFIX;
- static const char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1;
- static const char *const standard_startfile_prefix = STANDARD_STARTFILE_PREFIX;
--static const char *const standard_startfile_prefix_1 = "/lib/";
--static const char *const standard_startfile_prefix_2 = "/usr/lib/";
-+static const char *const standard_startfile_prefix_1 = STANDARD_STARTFILE_PREFIX_1;
-+static const char *const standard_startfile_prefix_2 = STANDARD_STARTFILE_PREFIX_2;
-
- static const char *const tooldir_base_prefix = TOOLDIR_BASE_PREFIX;
- static const char *tooldir_prefix;
-@@ -4483,7 +4496,9 @@
- and it is better not to use them for searching
- at run time. In particular, stage1 loses. */
- if (!IS_ABSOLUTE_PATH (pl->prefix))
-+#ifndef VOL_SEPARATOR
- continue;
-+#endif /* VOL_SEPARATOR */
- #endif
- /* Try subdirectory if there is one. */
- if (multilib_dir != NULL
-@@ -5853,12 +5868,11 @@
- /* Exclude directories that the linker is known to search. */
- if (linker
- && ((cp - path == 6
-- && strcmp (path, concat (dir_separator_str, "lib",
-- dir_separator_str, ".", NULL)) == 0)
-+ && strcmp (path, concat (STANDARD_STARTFILE_PREFIX_1,
-+ ".", NULL)) == 0)
- || (cp - path == 10
-- && strcmp (path, concat (dir_separator_str, "usr",
-- dir_separator_str, "lib",
-- dir_separator_str, ".", NULL)) == 0)))
-+ && strcmp (path, concat (STANDARD_STARTFILE_PREFIX_2,
-+ ".", NULL)) == 0)))
- return 0;
-
- return (stat (path, &st) >= 0 && S_ISDIR (st.st_mode));
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.ginclude.stdarg.h.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.ginclude.stdarg.h.p
deleted file mode 100644
index 934c0c9..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.ginclude.stdarg.h.p
+++ /dev/null
@@ -1,20 +0,0 @@
---- gcc-3.4.6/gcc/ginclude/stdarg.h 2003-03-13 03:58:40.000000000 +0100
-+++ gcc/ginclude/stdarg.h 2013-05-19 20:23:32.000000000 +0200
-@@ -93,7 +93,7 @@
- But on BSD NET2 we must not test or define or undef it.
- (Note that the comments in NET 2's ansi.h
- are incorrect for _VA_LIST_--see stdio.h!) */
--#if !defined (_VA_LIST_) || defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__) || defined(WINNT)
-+#if !defined (_VA_LIST_) || defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__) || defined(WINNT) || defined(__amigaos__)
- /* The macro _VA_LIST_DEFINED is used in Windows NT 3.5 */
- #ifndef _VA_LIST_DEFINED
- /* The macro _VA_LIST is used in SCO Unix 3.2. */
-@@ -107,7 +107,7 @@
- #endif /* not _VA_LIST_T_H */
- #endif /* not _VA_LIST */
- #endif /* not _VA_LIST_DEFINED */
--#if !(defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__))
-+#if !(defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__) || defined(__amigaos__))
- #define _VA_LIST_
- #endif
- #ifndef _VA_LIST
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.loop.c.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.loop.c.p
deleted file mode 100644
index 6040ce4..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.loop.c.p
+++ /dev/null
@@ -1,13 +0,0 @@
---- gcc-3.4.6/gcc/loop.c 2013-05-19 20:09:27.000000000 +0200
-+++ gcc/loop.c 2013-05-19 20:23:32.000000000 +0200
-@@ -934,6 +934,10 @@
- == INSN_UID (regs->array[regno].single_usage))
- && regs->array[regno].set_in_loop == 1
- && GET_CODE (SET_SRC (set)) != ASM_OPERANDS
-+ && (regno >= FIRST_PSEUDO_REGISTER
-+ || asm_noperands (PATTERN (regs->array[regno]
-+ .single_usage))
-+ < 0)
- && ! side_effects_p (SET_SRC (set))
- && ! find_reg_note (p, REG_RETVAL, NULL_RTX)
- && (! SMALL_REGISTER_CLASSES
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.mklibgcc.in.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.mklibgcc.in.p
deleted file mode 100644
index a169484..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.mklibgcc.in.p
+++ /dev/null
@@ -1,13 +0,0 @@
---- gcc-3.4.6/gcc/mklibgcc.in 2013-05-19 20:09:27.000000000 +0200
-+++ gcc/mklibgcc.in 2013-05-19 20:23:32.000000000 +0200
-@@ -42,6 +42,10 @@
- # SHLIB_INSTALL
- # MULTILIB_OSDIRNAMES
-
-+if [ "$LIBGCC_MULTI" != '' ]; then
-+ MULTILIBS=$LIBGCC_MULTI
-+fi
-+
- # Make needs VPATH to be literal.
- echo 'srcdir = @srcdir@'
- echo 'VPATH = @srcdir@'
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.opts.c.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.opts.c.p
deleted file mode 100644
index 1eb8198..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.opts.c.p
+++ /dev/null
@@ -1,26 +0,0 @@
---- gcc-3.4.6/gcc/opts.c 2004-02-18 01:09:04.000000000 +0100
-+++ gcc/opts.c 2013-05-19 20:23:32.000000000 +0200
-@@ -619,7 +619,7 @@
-
- if (flag_pie)
- flag_pic = flag_pie;
-- if (flag_pic && !flag_pie)
-+ if (flag_pic && flag_pic < 3 && !flag_pie)
- flag_shlib = 1;
-
- if (flag_no_inline == 2)
-@@ -889,6 +889,14 @@
- flag_bounds_check = value;
- break;
-
-+ case OPT_fbaserel:
-+ flag_pic = value + value + value;
-+ break;
-+
-+ case OPT_fbaserel32:
-+ flag_pic = value + value + value + value;
-+ break;
-+
- case OPT_fbranch_count_reg:
- flag_branch_on_count_reg = value;
- break;
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.rtl.h.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.rtl.h.p
deleted file mode 100644
index 779a3e9..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.rtl.h.p
+++ /dev/null
@@ -1,11 +0,0 @@
---- gcc-3.4.6/gcc/rtl.h 2013-05-19 20:22:04.000000000 +0200
-+++ gcc/rtl.h 2013-05-19 20:23:32.000000000 +0200
-@@ -587,7 +587,7 @@
- JUMP_INSN, INSN_LIST, BARRIER, CODE_LABEL, CONST, \
- NOTE)->integrated)
- #define RTX_UNCHANGING_P(RTX) \
-- (RTL_FLAG_CHECK3("RTX_UNCHANGING_P", (RTX), REG, MEM, CONCAT)->unchanging)
-+ (RTL_FLAG_CHECK4("RTX_UNCHANGING_P", (RTX), REG, MEM, CONCAT, PLUS)->unchanging)
- #define RTX_FRAME_RELATED_P(RTX) \
- (RTL_FLAG_CHECK5("RTX_FRAME_RELATED_P", (RTX), INSN, CALL_INSN, \
- JUMP_INSN, BARRIER, SET)->frame_related)
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.toplev.c.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.toplev.c.p
deleted file mode 100644
index 8eecf05..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.toplev.c.p
+++ /dev/null
@@ -1,11 +0,0 @@
---- gcc-3.4.6/gcc/toplev.c 2013-05-19 20:09:28.000000000 +0200
-+++ gcc/toplev.c 2013-05-19 20:23:32.000000000 +0200
-@@ -1100,6 +1100,8 @@
- {"branch-count-reg",&flag_branch_on_count_reg, 1 },
- {"pic", &flag_pic, 1 },
- {"PIC", &flag_pic, 2 },
-+ {"baserel", &flag_pic, 3 },
-+ {"baserel32", &flag_pic, 4 },
- {"pie", &flag_pie, 1 },
- {"PIE", &flag_pie, 2 },
- {"exceptions", &flag_exceptions, 1 },
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc6.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc6.p
new file mode 100644
index 0000000..c3dcdb7
--- /dev/null
+++ b/m68k-unknown-amigaos/recipes/patches/gcc/gcc6.p
@@ -0,0 +1,42963 @@
+From 64dc72223bfc308f487ea8c70c6f961075cd4f24 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 1 Dec 2016 00:19:04 +0100
+Subject: [PATCH 001/303] @R add support for m68k-*-amiga
+
+---
+ gcc/Makefile.in | 2 +-
+ gcc/amigacollect2.c | 348 ++++++++++++++++++
+ gcc/c/c-decl.c | 78 ++++
+ gcc/c/c-parser.c | 18 +-
+ gcc/c/c-tree.h | 4 +
+ gcc/calls.c | 2 +-
+ gcc/collect2.c | 31 ++
+ gcc/config.gcc | 10 +
+ gcc/config/m68k/amigaos-protos.h | 58 +++
+ gcc/config/m68k/amigaos.c | 773 +++++++++++++++++++++++++++++++++++++++
+ gcc/config/m68k/amigaos.h | 490 +++++++++++++++++++++++++
+ gcc/config/m68k/amigaos.opt | 13 +
+ gcc/config/m68k/host-amigaos.c | 42 +++
+ gcc/config/m68k/m68k.c | 30 +-
+ gcc/config/m68k/m68k.h | 5 +
+ gcc/config/m68k/m68k.md | 2 +
+ gcc/config/m68k/m68kamigaos.h | 424 +++++++++++++++++++++
+ gcc/config/m68k/m68kemb.h | 2 +
+ gcc/config/m68k/t-amigaos | 30 ++
+ gcc/config/m68k/x-amigaos | 104 ++++++
+ gcc/config/m68k/xm-amigaos.h | 64 ++++
+ gcc/expr.c | 2 +-
+ gcc/function.c | 2 +-
+ gcc/ipa-chkp.c | 2 +
+ gcc/tree-chkp.c | 1 +
+ gcc/var-tracking.c | 2 +-
+ libstdc++-v3/configure | 4 +
+ 27 files changed, 2533 insertions(+), 10 deletions(-)
+ create mode 100755 gcc/amigacollect2.c
+ create mode 100755 gcc/config/m68k/amigaos-protos.h
+ create mode 100755 gcc/config/m68k/amigaos.c
+ create mode 100755 gcc/config/m68k/amigaos.h
+ create mode 100755 gcc/config/m68k/amigaos.opt
+ create mode 100755 gcc/config/m68k/host-amigaos.c
+ create mode 100755 gcc/config/m68k/m68kamigaos.h
+ create mode 100755 gcc/config/m68k/t-amigaos
+ create mode 100755 gcc/config/m68k/x-amigaos
+ create mode 100755 gcc/config/m68k/xm-amigaos.h
+
+diff --git a/gcc/Makefile.in b/gcc/Makefile.in
+index 513f9c57013f..c1986279752f 100644
+--- gcc/Makefile.in
++++ gcc/Makefile.in
+@@ -1985,7 +1985,7 @@ gcc-nm.c: gcc-ar.c
+ cp $^ $@
+
+ COLLECT2_OBJS = collect2.o collect2-aix.o tlink.o vec.o ggc-none.o \
+- collect-utils.o file-find.o hash-table.o
++ collect-utils.o file-find.o hash-table.o $(EXTRA_COLLECT2_OBJS)
+ COLLECT2_LIBS = @COLLECT2_LIBS@
+ collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS)
+ # Don't try modifying collect2 (aka ld) in place--it might be linking this.
+diff --git a/gcc/amigacollect2.c b/gcc/amigacollect2.c
+new file mode 100755
+index 000000000000..941ea0248fbe
+--- /dev/null
++++ gcc/amigacollect2.c
+@@ -0,0 +1,348 @@
++/* GG-local whole file: dynamic libraries */
++/* Supplimentary functions that get compiled and linked to collect2 for
++ AmigaOS target.
++ Copyright (C) 1996 Free Software Foundation, Inc.
++
++This file is part of GCC.
++
++GCC 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.
++
++GCC 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 GCC; see the file COPYING. If not, write to
++the Free Software Foundation, 59 Temple Place - Suite 330,
++Boston, MA 02111-1307, USA. */
++
++#include "config.h"
++#include "system.h"
++#include "coretypes.h"
++#include "tm.h"
++
++/* From collect2.c: */
++
++void maybe_unlink(const char *);
++void fatal_error(location_t, const char *, ...);
++void fork_execute(const char *, char **, bool);
++
++extern char *c_file_name;
++extern int debug;
++
++/* Local functions. */
++
++static void safename (char *);
++static void add_lib (const char *);
++static void cat (const char *, FILE *);
++
++ /* Names of temporary files we create. */
++#define XLIBS_C_NAME "xlibs.c"
++#define XLIBS_O_NAME "xlibs.o"
++#define SHARED_X_NAME "shared.x"
++
++/* Suffix which is prepended to "-l" options for dynamic libraries. */
++#define DYNAMIC_LIB_SUFFIX "_ixlibrary"
++
++/* Structure that holds library names. */
++struct liblist
++{
++ struct liblist *next;
++ char *name;
++ char *cname;
++};
++
++/* Not zero if "-static" was specified on GCC command line or if all the
++ libraries are static. */
++static int flag_static=0;
++
++/* Not zero if linking a base relative executable. This is recognized by
++ presence of "-m amiga_bss" on the linker's commandline. */
++static int flag_baserel=0;
++
++/* Not zero if some of the specified libraries are dynamic. */
++static int found_dynamic_libs=0;
++
++/* List of linker libraries. */
++struct liblist *head = NULL;
++
++ /* Return 1 if collect2 should do something more apart from tlink. We want it
++ to call "postlink" and "strip" if linking with dynamic libraries. */
++
++int
++amigaos_do_collecting (void)
++{
++ return !flag_static;
++}
++
++/* Check for presence of "-static" on the GCC command line. We should not do
++ collecting if this flag was specified. */
++
++void
++amigaos_gccopts_hook (const char *arg)
++{
++ if (strncmp(arg, "-static", strlen("-static"))==0)
++ flag_static=1;
++}
++
++/* Replace unprintable characters with underscores. Used by "add_lib()". */
++
++static void
++safename (char *p)
++{
++ if (!ISALPHA(*p))
++ *p = '_';
++ p++;
++ while (*p)
++ {
++ if (!ISALNUM(*p))
++ *p = '_';
++ p++;
++ }
++}
++
++/* Add a library to the list of dynamic libraries. First make sure that the
++ library is actually dynamic. Used by "amigaos_libname_hook()". */
++
++static void
++add_lib (const char *name)
++{
++ struct liblist *lib;
++ static char buf[256];
++
++ for (lib = head; lib; lib = lib->next)
++ if (!strcmp(lib->name, name))
++ return;
++
++ /* A2IXDIR_PREFIX is passed by "make". */
++ sprintf(buf, A2IXDIR_PREFIX "/ldscripts/%s.x", name);
++ if (access(buf, R_OK))
++ return;
++
++ lib = (struct liblist*)xmalloc(sizeof(struct liblist));
++ lib->name = xstrdup(name);
++ lib->cname = xstrdup(name);
++ safename(lib->cname);
++ lib->next = head;
++ head = lib;
++
++ if (debug)
++ fprintf(stderr, "found dynamic library, name: %s, cname: %s\n", lib->name,
++ lib->cname);
++
++ found_dynamic_libs=1;
++}
++
++/* Check if the argument is a linker library. Call "add_lib()" if yes. */
++
++void
++amigaos_libname_hook (const char *arg)
++{
++ int len = strlen(arg);
++ if (flag_static)
++ return;
++
++ if (len > 2 && !memcmp(arg, "-l", 2))
++ add_lib(arg + 2);
++ else if (len > 2 && !strcmp(arg + len - 2, ".a"))
++ {
++ const char *lib;
++
++ ((char*)arg)[len - 2] = '\0';
++ lib = strrchr(arg, '/');
++ if (lib == NULL)
++ lib = strrchr(arg, ':');
++ if (lib == NULL)
++ lib = arg - 1;
++ if (!strncmp(lib + 1, "lib", 3))
++ add_lib(lib + 4);
++ ((char *)arg)[len - 2] = '.';
++ }
++}
++
++/* Delete temporary files. */
++
++void
++amigaos_collect2_cleanup (void)
++{
++ if (flag_static)
++ return;
++ maybe_unlink(XLIBS_C_NAME);
++ maybe_unlink(XLIBS_O_NAME);
++ maybe_unlink(SHARED_X_NAME);
++}
++
++/* Copy file named by FNAME to X. */
++
++static void
++cat (const char *fname, FILE *x)
++{
++#define BUFSIZE 16384
++ FILE *in;
++ static char buf[BUFSIZE];
++ int bytes;
++
++ in = fopen(fname, "r");
++ if (in == NULL)
++ fatal_error (input_location, "%s", fname);
++ while (!feof(in) && (bytes = fread(buf, 1, BUFSIZE, in)))
++ fwrite(buf, 1, bytes, x);
++ fclose(in);
++}
++
++/* If no dynamic libraries were found, perform like "-static". Otherwise,
++ create "xlibs.c", "shared.x" and invoke "gcc" to create "xlibs.o". We also
++ have to adjust the linker commandline. */
++
++void
++amigaos_prelink_hook (const char **ld1_argv, int *strip_flag)
++{
++ if (flag_static)
++ return;
++
++ if (!found_dynamic_libs)
++ {
++ flag_static=1;
++ /* If the user has not requested "-static", but has requested "-s",
++ collect2 removes "-s" from the "ld1_argv", and calls "strip" after
++ linking. However, this would not be efficient if we linked the
++ executable without any dynamic library. In this case, we put "-s"
++ back. */
++ if (*strip_flag)
++ {
++ /* Add "-s" as the last argument on the command line. */
++ while (*ld1_argv)
++ ld1_argv++;
++ *ld1_argv++="-s";
++ *ld1_argv=0;
++ *strip_flag=0;
++ }
++ }
++ else
++ {
++ FILE *x, *out;
++ struct liblist *lib;
++ static const char* argv[]={0, "-c", XLIBS_C_NAME, 0};
++ const char **ld1_end, **ld1;
++
++ /* Prepend suffixes to dynamic lib names. In addition, check if we are
++ linking a base relative executable. */
++ for (ld1=ld1_argv; *ld1; ld1++)
++ {
++ int len=strlen(*ld1);
++ if (strncmp(*ld1, "-l", strlen("-l"))==0)
++ {
++ for (lib=head; lib; lib=lib->next)
++ if (strcmp(*ld1+strlen("-l"), lib->name)==0)
++ {
++ char *newname=(char*)
++ xmalloc(strlen(*ld1)+strlen(DYNAMIC_LIB_SUFFIX)+1);
++ strcpy(newname, *ld1);
++ strcat(newname, DYNAMIC_LIB_SUFFIX);
++ *ld1=newname;
++ break;
++ }
++ }
++ else if (len > 2 && !strcmp(*ld1 + len - 2, ".a"))
++ {
++ const char *libname;
++ int substituted=0;
++
++ ((char *)(*ld1))[len - 2] = '\0';
++ libname = strrchr(*ld1, '/');
++ if (libname == NULL)
++ libname = strrchr(*ld1, ':');
++ if (libname == NULL)
++ libname = *ld1 - 1;
++ if (!strncmp(libname + 1, "lib", 3))
++ for (lib=head; lib; lib=lib->next)
++ if (strcmp(libname+4, lib->name)==0)
++ {
++ char *newname=(char*)xmalloc(strlen(*ld1)+
++ strlen(DYNAMIC_LIB_SUFFIX)+3);
++ strcpy(newname, *ld1);
++ strcat(newname, DYNAMIC_LIB_SUFFIX);
++ strcat(newname, ".a");
++ *ld1=newname;
++ substituted=1;
++ break;
++ }
++ if (!substituted)
++ ((char *)(*ld1))[len - 2] = '.';
++ }
++ else if (strcmp(ld1[0], "-m")==0 && ld1[1]
++ && strcmp(ld1[1], "amiga_bss")==0)
++ {
++ flag_baserel=1;
++ break;
++ }
++ }
++
++ out = fopen(XLIBS_C_NAME, "w");
++ if (out == NULL)
++ fatal_error (input_location, "%s", XLIBS_C_NAME);
++ x = fopen(SHARED_X_NAME, "w");
++ if (x == NULL)
++ fatal_error (input_location, "%s", SHARED_X_NAME);
++
++ cat((flag_baserel ? A2IXDIR_PREFIX "/amiga_exe_baserel_script.x"
++ : A2IXDIR_PREFIX "/amiga_exe_script.x"), x);
++ for (lib = head; lib; lib = lib->next)
++ {
++ static char buf[256];
++ sprintf(buf, A2IXDIR_PREFIX "/ldscripts/%s.x", lib->name);
++ fprintf(out, "extern long %sBase; long *__p%sBase = &%sBase;\n",
++ lib->cname, lib->cname, lib->cname);
++ cat(buf, x);
++ } /* {{ */
++ fprintf(x, "}}\n");
++ fclose(out);
++ fclose(x);
++ argv[0]=c_file_name;
++ fork_execute("gcc", (char **)argv, false);
++
++ /* Unfortunately, unlike "-s", "-T" cannot be specified as the last
++ argument. We put it after "-L" args. */
++ ld1_end=ld1_argv;
++ while (*ld1_end)
++ ld1_end++;
++ ld1_end++;
++ /* "ld1_end" now points after the terminating 0 of "ld1_argv". */
++
++ ld1=ld1_end-2;
++ while (ld1>ld1_argv && strncmp(*ld1, "-L", strlen("-L")))
++ ld1--;
++ if (ld1==ld1_argv)
++ fatal_error (input_location, "no -L arguments");
++ ld1++;
++ /* "ld1" now points after "-L". */
++
++ /* Shift all the arguments after "-L" one position right. */
++ memmove(ld1+1, ld1, (ld1_end-ld1)*sizeof(*ld1));
++ /* Put -Tshared.x in the now empty space. */
++ *ld1="-T" SHARED_X_NAME;
++ }
++}
++
++/* Be lazy and just call "postlink". */
++
++void
++amigaos_postlink_hook (const char *output_file)
++{
++ static const char *argv[]={"postlink", 0, 0, 0};
++ if (flag_static)
++ return;
++
++ if (flag_baserel)
++ {
++ argv[1]="-baserel";
++ argv[2]=output_file;
++ }
++ else
++ argv[1]=output_file;
++ fork_execute("postlink", (char **)argv, false);
++}
+diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
+index b237e93b927d..3107bdfac430 100644
+--- gcc/c/c-decl.c
++++ gcc/c/c-decl.c
+@@ -51,6 +51,8 @@ along with GCC; see the file COPYING3. If not see
+ #include "c-family/c-ada-spec.h"
+ #include "cilk.h"
+ #include "builtins.h"
++#include "output.h"
++#include "tm_p.h"
+
+ /* In grokdeclarator, distinguish syntactic contexts of declarators. */
+ enum decl_context
+@@ -5024,6 +5026,29 @@ grokparm (const struct c_parm *parm, tree *expr)
+ return decl;
+ }
+
++#ifdef TARGET_AMIGA
++
++/* Create a new variant of TYPE, equivalent but distinct.
++ This is so the caller can modify it. */
++
++static tree
++build_type_copy (tree type)
++ {
++ tree t, m = TYPE_MAIN_VARIANT (type);
++
++ t = copy_node (type);
++
++ TYPE_POINTER_TO (t) = 0;
++ TYPE_REFERENCE_TO (t) = 0;
++
++ /* Add this type to the chain of variants of TYPE. */
++ TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
++ TYPE_NEXT_VARIANT (m) = t;
++
++ return t;
++ }
++#endif
++
+ /* Given a parsed parameter declaration, decode it into a PARM_DECL
+ and push that on the current scope. EXPR is a pointer to an
+ expression that needs to be evaluated for the side effects of array
+@@ -5041,6 +5066,59 @@ push_parm_decl (const struct c_parm *parm, tree *expr)
+
+ decl = pushdecl (decl);
+
++#ifdef TARGET_AMIGAOS
++ if (parm->asmspec)
++ {
++ tree atype = TREE_TYPE(decl);
++ const char *asmspec = TREE_STRING_POINTER(parm->asmspec);
++ if (*asmspec == '%')
++ ++asmspec;
++ int reg_number = decode_reg_name (asmspec);
++
++ /* First detect errors in declaring global registers. */
++ if (reg_number == -1)
++ error ("%Jregister name not specified for %qD", decl, decl);
++ else if (reg_number < 0)
++ error ("%Jinvalid register name for %qD", decl, decl);
++ else if (TYPE_MODE (TREE_TYPE (decl)) == BLKmode)
++ error ("%Jdata type of %qD isn%'t suitable for a register", decl, decl);
++ else if (!HARD_REGNO_MODE_OK(reg_number, TYPE_MODE (TREE_TYPE (decl))))
++ error ("%Jregister specified for %qD isn%'t suitable for data type",
++ decl, decl);
++ /* Now handle properly declared static register variables. */
++ else
++ {
++ /* Build tree for __attribute__ ((asm(regnum))). */
++ FIXED_VALUE_TYPE fv =
++ { reg_number, 0, BImode };
++ tree ttasm = get_identifier("asm");
++ tree t, attrs = tree_cons(ttasm, build_fixed (ttasm, fv), NULL_TREE);
++ /* First check whether such a type already exists - if yes, use
++ that one. This is very important, since otherwise
++ common_type() would think that it sees two different
++ types and would try to merge them - this could result in
++ warning messages. */
++ for (t = TYPE_MAIN_VARIANT(atype); t; t = TYPE_NEXT_VARIANT(t))
++ if (comptypes (t, atype) == 1
++ && attribute_list_equal (TYPE_ATTRIBUTES(t), attrs))
++ break;
++ if (t)
++ atype = t;
++ else
++ {
++ /* Create a new variant, with differing attributes.
++ (Hack! Type with differing attributes should no longer be
++ a variant of its main type. See comment above for
++ explanation why this was necessary). */
++ atype = build_type_copy (atype);
++ TYPE_ATTRIBUTES(atype) = chainon (attrs, TYPE_ATTRIBUTES(atype));
++ }
++ TREE_TYPE(decl) = atype;
++// printf("%s using %s, cdecl=%p, type=%p\n", IDENTIFIER_POINTER(DECL_NAME (decl), asmspec, decl, atype);
++ }
++ }
++#endif
++
+ finish_decl (decl, input_location, NULL_TREE, NULL_TREE, NULL_TREE);
+ }
+
+diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
+index c9eb8ddbae3a..d8725b572b55 100644
+--- gcc/c/c-parser.c
++++ gcc/c/c-parser.c
+@@ -3837,10 +3837,26 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
+ c_parser_skip_until_found (parser, CPP_COMMA, NULL);
+ return NULL;
+ }
++ /**
++ * SBF: Add support for __asm("xy") register spec.
++ */
++#ifdef TARGET_AMIGAOS
++ tree asmspec = NULL_TREE;
++ if (c_parser_next_token_is_keyword (parser, RID_ASM))
++ {
++ asmspec = c_parser_simple_asm_expr (parser);
++// printf("asmspec: %s\n", TREE_STRING_POINTER(asmspec));
++ }
++#endif
+ if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+ postfix_attrs = c_parser_attributes (parser);
+- return build_c_parm (specs, chainon (postfix_attrs, prefix_attrs),
++
++ struct c_parm * cparm = build_c_parm (specs, chainon (postfix_attrs, prefix_attrs),
+ declarator);
++#ifdef TARGET_AMIGAOS
++ cparm->asmspec = asmspec;
++#endif
++ return cparm;
+ }
+
+ /* Parse a string literal in an asm expression. It should not be
+diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
+index bb12a200f709..e3404fd8b0a6 100644
+--- gcc/c/c-tree.h
++++ gcc/c/c-tree.h
+@@ -453,6 +453,10 @@ struct c_parm {
+ tree attrs;
+ /* The declarator. */
+ struct c_declarator *declarator;
++#ifdef TARGET_AMIGAOS
++ /* The optional asm spec to specify the register. */
++ tree asmspec;
++#endif
+ };
+
+ /* Used when parsing an enum. Initialized by start_enum. */
+diff --git a/gcc/calls.c b/gcc/calls.c
+index 6cc1fc721e45..e5188b93ba94 100644
+--- gcc/calls.c
++++ gcc/calls.c
+@@ -21,12 +21,12 @@ along with GCC; see the file COPYING3. If not see
+ #include "system.h"
+ #include "coretypes.h"
+ #include "backend.h"
++#include "tm_p.h"
+ #include "target.h"
+ #include "rtl.h"
+ #include "tree.h"
+ #include "gimple.h"
+ #include "predict.h"
+-#include "tm_p.h"
+ #include "stringpool.h"
+ #include "expmed.h"
+ #include "optabs.h"
+diff --git a/gcc/collect2.c b/gcc/collect2.c
+index bffac802b8fe..f52a66ef1b58 100644
+--- gcc/collect2.c
++++ gcc/collect2.c
+@@ -1392,6 +1392,11 @@ main (int argc, char **argv)
+ add_to_list (&libs, s);
+ }
+ #endif
++ /* begin-GG-local: dynamic libraries */
++ #ifdef COLLECT2_LIBNAME_HOOK
++ COLLECT2_LIBNAME_HOOK(arg);
++ #endif
++ /* end-GG-local */
+ break;
+
+ #ifdef COLLECT_EXPORT_LIST
+@@ -1492,6 +1497,11 @@ main (int argc, char **argv)
+ add_to_list (&libs, arg);
+ }
+ #endif
++ /* begin-GG-local: dynamic libraries */
++#ifdef COLLECT2_LIBNAME_HOOK
++ COLLECT2_LIBNAME_HOOK(arg);
++#endif
++ /* end-GG-local */
+ }
+ }
+
+@@ -1608,6 +1618,11 @@ main (int argc, char **argv)
+
+ fprintf (stderr, "\n");
+ }
++ /* begin-GG-local: dynamic libraries */
++#ifdef COLLECT2_PRELINK_HOOK
++ COLLECT2_PRELINK_HOOK(ld1_argv, &strip_flag);
++#endif
++ /* end-GG-local */
+
+ /* Load the program, searching all libraries and attempting to provide
+ undefined symbols from repository information.
+@@ -1648,6 +1663,8 @@ main (int argc, char **argv)
+ }
+ }
+
++ /* begin-GG-local: dynamic libraries */
++#ifndef COLLECT2_POSTLINK_HOOK
+ /* Unless we have done it all already, examine the namelist and search for
+ static constructors and destructors to call. Write the constructor and
+ destructor tables to a .s file and reload. */
+@@ -1674,6 +1691,10 @@ main (int argc, char **argv)
+ frame_tables.number),
+ frame_tables.number);
+ }
++#else /* COLLECT2_POSTLINK_HOOK */
++ COLLECT2_POSTLINK_HOOK(output_file);
++#endif
++/* end-GG-local */
+
+ /* If the scan exposed nothing of special interest, there's no need to
+ generate the glue code and relink so return now. */
+@@ -1716,6 +1737,11 @@ main (int argc, char **argv)
+
+ maybe_unlink (c_file);
+ maybe_unlink (o_file);
++ /* begin-GG-local: dynamic libraries */
++#ifdef COLLECT2_EXTRA_CLEANUP
++ COLLECT2_EXTRA_CLEANUP();
++#endif
++ /* end-GG-local */
+ return 0;
+ }
+
+@@ -1821,6 +1847,11 @@ main (int argc, char **argv)
+ maybe_unlink (export_file);
+ #endif
+
++ /* begin-GG-local: dynamic libraries */
++#ifdef COLLECT2_EXTRA_CLEANUP
++ COLLECT2_EXTRA_CLEANUP();
++#endif
++ /* end-GG-local */
+ return 0;
+ }
+
+diff --git a/gcc/config.gcc b/gcc/config.gcc
+index 1d5b23f228d2..3ef1a5f110f3 100644
+--- gcc/config.gcc
++++ gcc/config.gcc
+@@ -1931,6 +1931,16 @@ m68k-*-elf* | fido-*-elf*)
+ ;;
+ esac
+ ;;
++m68k*-*-amigaos*)
++ default_m68k_cpu=68000
++ tm_file="${tm_file} dbx.h newlib-stdint.h m68k/m68kamigaos.h"
++ tm_defines="${tm_defines} MOTOROLA=1 TARGET_AMIGAOS TARGET_CPU_DEFAULT=0"
++ tmake_file="m68k/t-floatlib m68k/t-m68kbare m68k/t-amigaos"
++ tm_p_file="${tm_p_file} m68k/amigaos-protos.h"
++ extra_objs=amigaos.o
++ extra_options="${extra_options} m68k/amigaos.opt"
++ gnu_ld=yes
++ ;;
+ m68k*-*-netbsdelf*)
+ default_m68k_cpu=68020
+ default_cf_cpu=5475
+diff --git a/gcc/config/m68k/amigaos-protos.h b/gcc/config/m68k/amigaos-protos.h
+new file mode 100755
+index 000000000000..66b553ab568f
+--- /dev/null
++++ gcc/config/m68k/amigaos-protos.h
+@@ -0,0 +1,58 @@
++/* Configuration for GNU C-compiler for m68k Amiga, running AmigaOS.
++ Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2003
++ Free Software Foundation, Inc.
++ Contributed by Markus M. Wild (wild@amiga.physik.unizh.ch).
++ Heavily modified by Kamil Iskra (iskra@student.uci.agh.edu.pl).
++
++This file is part of GCC.
++
++GCC 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.
++
++GCC 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 GCC; see the file COPYING. If not, write to
++the Free Software Foundation, 59 Temple Place - Suite 330,
++Boston, MA 02111-1307, USA. */
++
++#undef TARGET_AMIGAOS
++#define TARGET_AMIGAOS 1
++
++extern void amigaos_init_cumulative_args (CUMULATIVE_ARGS *, tree);
++
++/* Initialize a variable CUM of type CUMULATIVE_ARGS
++ for a call to a function whose data type is FNTYPE.
++ For a library call, FNTYPE is 0. */
++
++#undef INIT_CUMULATIVE_ARGS
++#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
++ (amigaos_init_cumulative_args(&(CUM), (FNTYPE)))
++
++
++extern int amigaos_restore_a4 (void);
++#ifdef RTX_CODE
++extern int read_only_operand (rtx);
++extern void amigaos_select_section (tree, int, unsigned HOST_WIDE_INT);
++extern void amigaos_encode_section_info (tree, rtx, int);
++extern void amigaos_alternate_pic_setup (FILE *);
++extern void amigaos_prologue_begin_hook (FILE *, int);
++extern void amigaos_alternate_frame_setup_f (FILE *, int);
++extern void amigaos_alternate_frame_setup (FILE *, int);
++extern struct rtx_def* gen_stack_cleanup_call (rtx, rtx);
++extern void amigaos_alternate_allocate_stack (rtx *);
++#ifdef TREE_CODE
++//extern void amigaos_function_arg_advance (CUMULATIVE_ARGS *);
++extern struct rtx_def *amigaos_function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree);
++#endif
++#endif
++#ifdef TREE_CODE
++extern tree amigaos_handle_decl_attribute (tree *, tree, tree, int, bool *);
++extern tree amigaos_handle_type_attribute (tree *, tree, tree, int, bool *);
++#endif
++
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+new file mode 100755
+index 000000000000..90bc3218bab7
+--- /dev/null
++++ gcc/config/m68k/amigaos.c
+@@ -0,0 +1,773 @@
++/* Configuration for GNU C-compiler for m68k Amiga, running AmigaOS.
++ Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2003
++ Free Software Foundation, Inc.
++ Contributed by Markus M. Wild (wild@amiga.physik.unizh.ch).
++ Heavily modified by Kamil Iskra (iskra@student.uci.agh.edu.pl).
++
++This file is part of GCC.
++
++GCC 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.
++
++GCC 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 GCC; see the file COPYING. If not, write to
++the Free Software Foundation, 59 Temple Place - Suite 330,
++Boston, MA 02111-1307, USA. */
++
++//work without flag_writable_strings which is not in GCC4
++#define REGPARMS_68K 1
++
++#include "config.h"
++#include "system.h"
++#include "coretypes.h"
++#include "tm.h"
++#include "rtl.h"
++#include "output.h"
++#include "tree.h"
++#include "attribs.h"
++#include "flags.h"
++#include "expr.h"
++#include "toplev.h"
++#include "tm_p.h"
++#include "target.h"
++#include "diagnostic-core.h"
++#include "config/m68k/amigaos.h"
++
++
++#if 0
++static int amigaos_put_in_text (tree);
++static rtx gen_stack_management_call (rtx, rtx, const char *);
++
++/* Baserel support. */
++
++/* Does operand (which is a symbolic_operand) live in text space? If
++ so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true.
++
++ This function is used in base relative code generation. */
++
++int
++read_only_operand (rtx operand)
++{
++ if (GET_CODE (operand) == CONST)
++ operand = XEXP (XEXP (operand, 0), 0);
++ if (GET_CODE (operand) == SYMBOL_REF)
++ return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand);
++ return 1;
++}
++
++/* Choose the section to use for DECL. RELOC is true if its value contains
++ any relocatable expression. */
++
++void
++amigaos_select_section (tree decl ATTRIBUTE_UNUSED, int reloc ATTRIBUTE_UNUSED,
++ unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
++{
++ // if (TREE_CODE (decl) == STRING_CST)
++// {
++//// flag_writable_strings /data_section not in gcc4,
++////make life easy and put to same section
++//// if (! flag_writable_strings)
++//// readonly_data_section ();
++//// else
++// //data_section ();
++// }
++// else if (TREE_CODE (decl) == VAR_DECL)
++// {
++// if (TREE_READONLY (decl)
++// && ! TREE_THIS_VOLATILE (decl)
++// && DECL_INITIAL (decl)
++// && (DECL_INITIAL (decl) == error_mark_node
++// || TREE_CONSTANT (DECL_INITIAL (decl)))
++// && (!flag_pic || (flag_pic<3 && !reloc)
++// || SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0))))
++// readonly_data_section ();
++// else
++// data_section ();
++// }
++// else if ((!flag_pic || (flag_pic<3 && !reloc)) && DECL_P(decl)
++// && SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)))
++// readonly_data_section ();
++// else
++ //data_section ();
++}
++
++/* This function is used while generating a base relative code.
++ It returns 1 if a decl is not relocatable, i. e., if it can be put
++ in the text section.
++ Currently, it's very primitive: it just checks if the object size
++ is less than 4 bytes (i. e., if it can hold a pointer). It also
++ supports arrays and floating point types. */
++
++static int
++amigaos_put_in_text (tree decl)
++{
++ tree type = TREE_TYPE (decl);
++ if (TREE_CODE (type) == ARRAY_TYPE)
++ type = TREE_TYPE (type);
++ return (TREE_INT_CST_ELT(TYPE_SIZE (type), 1) == 0
++ && TREE_INT_CST_LOW (TYPE_SIZE (type)) < 32)
++ || FLOAT_TYPE_P (type);
++}
++
++/* Record properties of a DECL into the associated SYMBOL_REF. */
++
++void
++amigaos_encode_section_info (tree decl, rtx rtl, int first)
++{
++ default_encode_section_info (decl, rtl, first);
++
++
++ SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
++ if (TREE_CODE (decl) == FUNCTION_DECL) // huh seem do same. not in gcc4 flag_writable_strings
++ SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
++ else
++ {
++ if ((MEM_READONLY_P (rtl) && !MEM_VOLATILE_P (rtl)
++ && (flag_pic<3 || (TREE_CODE (decl) == STRING_CST
++ )
++ || amigaos_put_in_text (decl)))
++ || (TREE_CODE (decl) == VAR_DECL
++ && DECL_SECTION_NAME (decl) != NULL))
++ SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
++ }
++}
++
++/* Common routine used to check if a4 should be preserved/restored. */
++
++int
++amigaos_restore_a4 (void)
++{
++ return (flag_pic >= 3 &&
++ (TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4
++ || lookup_attribute ("saveds",
++ TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))));
++}
++
++void
++amigaos_alternate_pic_setup (FILE *stream)
++{
++ if (TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4)
++ asm_fprintf (stream, "\tjbsr %U__restore_a4\n");
++ else if (lookup_attribute ("saveds",
++ TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
++ asm_fprintf (stream, "\tlea %U__a4_init,%Ra4\n");
++}
++
++/* Attributes support. */
++
++#define AMIGA_CHIP_SECTION_NAME ".datachip"
++
++/* Handle a "chip" attribute;
++ arguments as in struct attribute_spec.handler. */
++
++tree
++amigaos_handle_decl_attribute (tree *node, tree name,
++ tree args ATTRIBUTE_UNUSED,
++ int flags ATTRIBUTE_UNUSED,
++ bool *no_add_attrs)
++{
++ if (TREE_CODE (*node) == VAR_DECL)
++ {
++ if (is_attribute_p ("chip", name))
++#ifdef TARGET_ASM_NAMED_SECTION
++ {
++ if (! TREE_STATIC (*node) && ! DECL_EXTERNAL (*node))
++ error ("`chip' attribute cannot be specified for local variables");
++ else
++ {
++ /* The decl may have already been given a section attribute from
++ a previous declaration. Ensure they match. */
++ if (DECL_SECTION_NAME (*node) == NULL_TREE)
++ DECL_SECTION_NAME (*node) =
++ build_string (strlen (AMIGA_CHIP_SECTION_NAME) + 1,
++ AMIGA_CHIP_SECTION_NAME);
++ else if (strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (*node)),
++ AMIGA_CHIP_SECTION_NAME) != 0)
++ {
++ error_with_decl (*node,
++ "`chip' for `%s' conflicts with previous declaration");
++ }
++ }
++ }
++#else
++ error ("`chip' attribute is not supported for this target");
++#endif
++ }
++ else
++ {
++ warning (OPT_Wattributes, "`%s' attribute only applies to variables",
++ IDENTIFIER_POINTER (name));
++ *no_add_attrs = true;
++ }
++
++ return NULL_TREE;
++}
++
++//----- from 68k.c start
++
++
++
++
++
++
++/* Stack checking and automatic extension support. */
++
++void
++amigaos_prologue_begin_hook (FILE *stream, int fsize)
++{
++ if (TARGET_STACKCHECK)
++ {
++ if (fsize < 256)
++ asm_fprintf (stream, "\tcmpl %s,%Rsp\n"
++ "\tjcc 0f\n"
++ "\tjra %U__stkovf\n"
++ "\t0:\n",
++ (flag_pic == 3 ? "a4@(___stk_limit:W)" :
++ (flag_pic == 4 ? "a4@(___stk_limit:L)" :
++ "___stk_limit")));
++ else
++ asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__stkchk_d0\n",
++ fsize);
++ }
++}
++
++void
++amigaos_alternate_frame_setup_f (FILE *stream, int fsize)
++{
++ if (fsize < 128)
++ asm_fprintf (stream, "\tcmpl %s,%Rsp\n"
++ "\tjcc 0f\n"
++ "\tmoveq %I%d,%Rd0\n"
++ "\tmoveq %I0,%Rd1\n"
++ "\tjbsr %U__stkext_f\n"
++ "0:\tlink %Ra5,%I%d:W\n",
++ (flag_pic == 3 ? "a4@(___stk_limit:W)" :
++ (flag_pic == 4 ? "a4@(___stk_limit:L)" :
++ "___stk_limit")),
++ fsize, -fsize);
++ else
++ asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__link_a5_d0_f\n",
++ fsize);
++}
++
++void
++amigaos_alternate_frame_setup (FILE *stream, int fsize)
++{
++ if (!fsize)
++ asm_fprintf (stream, "\tcmpl %s,%Rsp\n"
++ "\tjcc 0f\n"
++ "\tmoveq %I0,%Rd0\n"
++ "\tmoveq %I0,%Rd1\n"
++ "\tjbsr %U__stkext_f\n"
++ "0:\n",
++ (flag_pic == 3 ? "a4@(___stk_limit:W)" :
++ (flag_pic == 4 ? "a4@(___stk_limit:L)" :
++ "___stk_limit")));
++ else if (fsize < 128)
++ asm_fprintf (stream, "\tcmpl %s,%Rsp\n"
++ "\tjcc 0f\n"
++ "\tmoveq %I%d,%Rd0\n"
++ "\tmoveq %I0,%Rd1\n"
++ "\tjbsr %U__stkext_f\n"
++ "0:\taddw %I%d,%Rsp\n",
++ (flag_pic == 3 ? "a4@(___stk_limit:W)" :
++ (flag_pic == 4 ? "a4@(___stk_limit:L)" :
++ "___stk_limit")),
++ fsize, -fsize);
++ else
++ asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__sub_d0_sp_f\n",
++ fsize);
++}
++
++//static rtx
++//gen_stack_management_call (rtx stack_pointer, rtx arg, const char *func)
++//{
++// rtx call_insn, call, seq, name;
++// start_sequence ();
++//
++// /* Move arg to d0. */
++// emit_move_insn (gen_rtx_REG (SImode, 0), arg);
++//
++// /* Generate the function reference. */
++// name = gen_rtx_SYMBOL_REF (Pmode, func);
++// SYMBOL_REF_FLAG (name) = 1;
++// /* If optimizing, put it in a psedo so that several loads can be merged
++// into one. */
++// if (optimize && ! flag_no_function_cse)
++// name = copy_to_reg (name);
++//
++// /* Generate the function call. */
++// call = gen_rtx_CALL (VOIDmode, gen_rtx_MEM (FUNCTION_MODE, name),
++// const0_rtx);
++// /* If we are doing stack extension, notify about the sp change. */
++// if (stack_pointer)
++// call = gen_rtx_SET (VOIDmode, stack_pointer, call);
++//
++// /* Generate the call instruction. */
++// call_insn = emit_call_insn (call);
++// /* Stack extension does not change memory in an unpredictable way. */
++// RTL_CONST_OR_PURE_CALL_P (call_insn) = 1;
++// /* We pass an argument in d0. */
++// CALL_INSN_FUNCTION_USAGE (call_insn) = gen_rtx_EXPR_LIST (VOIDmode,
++// gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, 0)), 0);
++//
++// seq = get_insns ();
++// end_sequence ();
++// return seq;
++//}
++//
++//rtx
++//gen_stack_cleanup_call (rtx stack_pointer, rtx sa)
++//{
++// return gen_stack_management_call (stack_pointer, sa, "__move_d0_sp");
++//}
++//
++//void
++//amigaos_alternate_allocate_stack (rtx *operands)
++//{
++// if (TARGET_STACKEXTEND)
++// emit_insn (gen_stack_management_call (stack_pointer_rtx, operands[1],
++// "__sub_d0_sp"));
++// else
++// {
++// if (TARGET_STACKCHECK)
++// emit_insn (gen_stack_management_call (0, operands[1], "__stkchk_d0"));
++// anti_adjust_stack (operands[1]);
++// }
++// emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
++//}
++#endif
++
++/*
++ * begin-GG-local: explicit register specification for parameters.
++ *
++ * Reworked and ported to gcc-6.2.0 by Stefan "Bebbo" Franke.
++ */
++
++/**
++ * Define this here and add it to tm_p -> all know the custom type and allocate/use the correct size.
++ */
++struct amigaos_args
++{
++ int num_of_regs;
++ long regs_already_used;
++ int last_arg_reg;
++ int last_arg_len;
++ tree formal_type; /* New field: formal type of the current argument. */
++};
++
++static struct amigaos_args mycum;
++static CUMULATIVE_ARGS * lastcum;
++
++/* Argument-passing support functions. */
++
++/* Initialize a variable CUM of type CUMULATIVE_ARGS
++ for a call to a function whose data type is FNTYPE.
++ For a library call, FNTYPE is 0. */
++
++void
++amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype)
++{
++ struct amigaos_args * cum = &mycum;
++ lastcum = cump;
++ cum->num_of_regs = amigaos_regparm;
++// printf("amigaos_init_cumulative_args %p -> %d\r\n", cum, cum->num_of_regs); fflush(stdout);
++
++ /* Initialize a variable CUM of type CUMULATIVE_ARGS
++ for a call to a function whose data type is FNTYPE.
++ For a library call, FNTYPE is 0. */
++
++ cum->last_arg_reg = -1;
++ cum->regs_already_used = 0;
++
++ if (fntype)
++ {
++ if (lookup_attribute ("stkparm", TYPE_ATTRIBUTES(fntype)))
++ cum->num_of_regs = 0;
++ else
++ {
++ tree ratree = lookup_attribute ("regparm", TYPE_ATTRIBUTES(fntype));
++ cum->num_of_regs = amigaos_regparm ?
++ amigaos_regparm : AMIGAOS_DEFAULT_REGPARM;
++ if (ratree)
++ {
++ tree args = TREE_VALUE(ratree);
++
++ if (args && TREE_CODE (args) == TREE_LIST)
++ {
++ tree val = TREE_VALUE(args);
++ if (TREE_CODE (val) == INTEGER_CST)
++ {
++ int no = TREE_INT_CST_LOW(val);
++ if (no > 0 && no < AMIGAOS_MAX_REGPARM)
++ cum->num_of_regs = no;
++ }
++ }
++ }
++ }
++ }
++ else
++ /* Libcall. */
++ cum->num_of_regs = 0;
++
++ if (cum->num_of_regs)
++ {
++ /* If this is a vararg call, put all arguments on stack. */
++ tree param, next_param;
++ for (param = TYPE_ARG_TYPES(fntype); param; param = next_param)
++ {
++ next_param = TREE_CHAIN(param);
++ if (!next_param && TREE_VALUE (param) != void_type_node)
++ cum->num_of_regs = 0;
++ }
++ }
++
++ //#if ! defined (PCC_STATIC_STRUCT_RETURN) && defined (M68K_STRUCT_VALUE_REGNUM)
++ // /* If return value is a structure, and we pass the buffer address in a
++ // register, we can't use this register for our own purposes.
++ // FIXME: Something similar would be useful for static chain. */
++ // if (fntype && aggregate_value_p (TREE_TYPE (fntype), fntype))
++ // cum->regs_already_used |= (1 << M68K_STRUCT_VALUE_REGNUM);
++ //#endif
++
++ if (fntype)
++ cum->formal_type = TYPE_ARG_TYPES(fntype);
++ else
++ /* Call to compiler-support function. */
++ cum->formal_type = 0;
++}
++
++/* Update the data in CUM to advance over an argument. */
++
++void
++amigaos_function_arg_advance (cumulative_args_t cum_v, machine_mode, const_tree,
++ bool)
++{
++ struct amigaos_args * cum = &mycum;
++ CUMULATIVE_ARGS *cump = (CUMULATIVE_ARGS *) get_cumulative_args (cum_v);
++ /* Update the data in CUM to advance over an argument. */
++
++ // printf("amigaos_function_arg_advance1 %p\r\n", cump); fflush(stdout);
++ if (cump != lastcum)
++ return;
++
++ if (cum->last_arg_reg != -1)
++ {
++ int count;
++ for (count = 0; count < cum->last_arg_len; count++)
++ cum->regs_already_used |= (1 << (cum->last_arg_reg + count));
++ cum->last_arg_reg = -1;
++ }
++
++ if (cum->formal_type)
++ cum->formal_type = TREE_CHAIN(cum->formal_type);
++}
++
++/* Define where to put the arguments to a function.
++ Value is zero to push the argument on the stack,
++ or a hard register in which to store the argument.
++
++ MODE is the argument's machine mode.
++ TYPE is the data type of the argument (as a tree).
++ This is null for libcalls where that information may
++ not be available.
++ CUM is a variable of type CUMULATIVE_ARGS which gives info about
++ the preceding args and about the function being called. */
++
++static struct rtx_def *
++_m68k_function_arg (CUMULATIVE_ARGS *, machine_mode, const_tree);
++
++static struct rtx_def *
++_m68k_function_arg (CUMULATIVE_ARGS *cump, machine_mode mode, const_tree type)
++{
++ struct amigaos_args * cum = &mycum;
++ // printf("m68k_function_arg numOfRegs=%p\r\n", cum);
++
++ if (cump != lastcum)
++ return 0;
++
++ if (cum->num_of_regs)
++ {
++ int regbegin = -1, altregbegin = -1, len;
++
++ /* FIXME: The last condition below is a workaround for a bug. */
++ if (TARGET_68881 && FLOAT_MODE_P(mode) &&
++ GET_MODE_UNIT_SIZE (mode) <= 12
++ && (GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT || mode == SCmode))
++ {
++ regbegin = 16; /* FPx */
++ len = GET_MODE_NUNITS(mode);
++ }
++ /* FIXME: Two last conditions below are workarounds for bugs. */
++ else if (INTEGRAL_MODE_P (mode) && mode != CQImode && mode != CHImode)
++ {
++ if (POINTER_TYPE_P(type))
++ regbegin = 8; /* Ax */
++ else
++ regbegin = 0; /* Dx */
++ altregbegin = 8 - regbegin;
++ len = (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
++ }
++
++ if (regbegin != -1)
++ {
++ int reg;
++ long mask;
++
++ look_for_reg: mask = 1 << regbegin;
++ for (reg = 0; reg < cum->num_of_regs; reg++, mask <<= 1)
++ if (!(cum->regs_already_used & mask))
++ {
++ int end;
++ for (end = reg; end < cum->num_of_regs && end < reg + len;
++ end++, mask <<= 1)
++ if (cum->regs_already_used & mask)
++ break;
++ if (end == reg + len)
++ {
++ cum->last_arg_reg = reg + regbegin;
++ cum->last_arg_len = len;
++ break;
++ }
++ }
++
++ if (reg == cum->num_of_regs && altregbegin != -1)
++ {
++ regbegin = altregbegin;
++ altregbegin = -1;
++ goto look_for_reg;
++ }
++ }
++
++ if (cum->last_arg_reg != -1)
++ {
++ // printf("-> gen_rtx_REG %d\r\n", cum->last_arg_reg);
++ return gen_rtx_REG (mode, cum->last_arg_reg);
++ }
++ }
++ return 0;
++}
++
++/* A C expression that controls whether a function argument is passed
++ in a register, and which register. */
++
++struct rtx_def *
++amigaos_function_arg (cumulative_args_t cum_v, machine_mode mode,
++ const_tree type, bool)
++{
++ struct amigaos_args * cum = &mycum;
++
++ // printf("amigaos_function_arg %p\r\n", cum_v.p); fflush(stdout);
++
++ CUMULATIVE_ARGS *cump = (CUMULATIVE_ARGS *) get_cumulative_args (cum_v);
++
++ if (cump != lastcum)
++ return 0;
++
++ tree asmtree = type ? TYPE_ATTRIBUTES(type) : NULL_TREE;
++ if (asmtree && 0 == strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(asmtree))))
++ {
++ int i;
++ cum->last_arg_reg = TREE_FIXED_CST_PTR(TREE_VALUE(asmtree))->data.low;
++ cum->last_arg_len = HARD_REGNO_NREGS(cum->last_arg_reg, mode);
++
++ for (i = 0; i < cum->last_arg_len; i++)
++ if (cum->regs_already_used & (1 << (cum->last_arg_reg + i)))
++ {
++ error ("two parameters allocated for one register");
++ break;
++ }
++ return gen_rtx_REG (mode, cum->last_arg_reg);
++ }
++ return _m68k_function_arg (cump, mode, type);
++}
++
++/* Return zero if the attributes on TYPE1 and TYPE2 are incompatible,
++ one if they are compatible, and two if they are nearly compatible
++ (which causes a warning to be generated). */
++
++int
++amigaos_comp_type_attributes (const_tree type1, const_tree type2)
++{
++ printf("amigaos_comp_type_attributes\n");
++ /* Functions or methods are incompatible if they specify mutually exclusive
++ ways of passing arguments. */
++ if (TREE_CODE(type1) == FUNCTION_TYPE || TREE_CODE(type1) == METHOD_TYPE)
++ {
++ tree arg1, arg2;
++ arg1 = TYPE_ARG_TYPES(type1);
++ arg2 = TYPE_ARG_TYPES(type2);
++ for (; arg1 && arg2; arg1 = TREE_CHAIN(arg1), arg2 = TREE_CHAIN(arg2))
++ {
++ tree attr1 = TYPE_ATTRIBUTES(arg1);
++ tree attr2 = TYPE_ATTRIBUTES(arg2);
++ if (strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(attr1))))
++ attr1 = NULL_TREE;
++ if (strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(attr2))))
++ attr2 = NULL_TREE;
++ if (attr1 && attr2)
++ {
++ if (TREE_FIXED_CST_PTR(TREE_VALUE(attr1))->data.low
++ != TREE_FIXED_CST_PTR(TREE_VALUE(attr2))->data.low)
++ return 0;
++ }
++ else if (attr1 || attr2)
++ return 0; /* asm attribute only on one side. */
++ }
++ if (arg1 || arg2)
++ return 0; /* different count of parameters. */
++ }
++ return 1;
++}
++
++/* Return zero if the attributes on TYPE1 and TYPE2 are incompatible,
++ one if they are compatible, and two if they are nearly compatible
++ (which causes a warning to be generated). */
++#if 0
++static int
++m68k_comp_type_attributes (tree type1, tree type2)
++{
++
++ /* Functions or methods are incompatible if they specify mutually
++ exclusive ways of passing arguments. */
++ if (TREE_CODE (type1) == FUNCTION_TYPE || TREE_CODE (type1) == METHOD_TYPE)
++ {
++ tree arg1, arg2;
++ if (!! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type1)) !=
++ !! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type2))
++ || !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1)) !=
++ !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2)))
++ return 0; /* 'regparm' and 'stkparm' are mutually exclusive. */
++
++ arg1 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1));
++ arg2 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2));
++ if (arg1 && arg2)
++ {
++ int num1 = 0, num2 = 0;
++ if (TREE_VALUE (arg1) && TREE_CODE (TREE_VALUE (arg1)) == TREE_LIST)
++ {
++ tree numofregs = TREE_VALUE (TREE_VALUE (arg1));
++ if (numofregs)
++ num1 = TREE_INT_CST_LOW (numofregs);
++ }
++ if (TREE_VALUE (arg2) && TREE_CODE (TREE_VALUE (arg2)) == TREE_LIST)
++ {
++ tree numofregs = TREE_VALUE (TREE_VALUE (arg2));
++ if (numofregs)
++ num2 = TREE_INT_CST_LOW (numofregs);
++ }
++ if (num1 != num2)
++ return 0; /* Different numbers, or no number in one type. */
++ }
++ }
++#ifdef TARGET_AMIGAOS
++ return amigaos_comp_type_attributes(type1, type2);
++#else
++ return 1;
++#endif
++}
++#endif
++
++/* end-GG-local */
++
++
++/* Handle a "regparm", "stkparm" attribute;
++ arguments as in struct attribute_spec.handler. */
++tree
++amigaos_handle_type_attribute (tree *node, tree name, tree args,
++ int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
++{
++ tree nnn = *node;
++ do { // while (0);
++// printf("%p with treecode %d\n", node, TREE_CODE(nnn)); fflush(stdout);
++ if (TREE_CODE (nnn) == FUNCTION_DECL || TREE_CODE (nnn) == FUNCTION_TYPE
++ || TREE_CODE (nnn) == METHOD_TYPE)
++ {
++ /* 'regparm' accepts one optional argument - number of registers in
++ single class that should be used to pass arguments. */
++ if (is_attribute_p ("regparm", name))
++ {
++// printf ("regparm found\n"); fflush(stdout);
++
++ if (lookup_attribute ("stkparm", TYPE_ATTRIBUTES(nnn)))
++ {
++ error ("`regparm' and `stkparm' are mutually exclusive");
++ break;
++ }
++ if (args && TREE_CODE (args) == TREE_LIST)
++ {
++ tree val = TREE_VALUE(args);
++// printf ("regparm with val: %d\n", TREE_CODE(val));
++ if (TREE_CODE (val) == INTEGER_CST)
++ {
++ int no = TREE_INT_CST_LOW(val);
++ if (no < 0 || no > AMIGAOS_MAX_REGPARM)
++ {
++ error ("`regparm' attribute: value %d not in [0 - %d]",
++ no,
++ AMIGAOS_MAX_REGPARM);
++ break;
++ }
++ }
++ else
++ {
++ error ("invalid argument(s) to `regparm' attribute");
++ break;
++ }
++ }
++ }
++ else if (is_attribute_p ("stkparm", name))
++ {
++ if (lookup_attribute ("regparm", TYPE_ATTRIBUTES(nnn)))
++ {
++ error ("`regparm' and `stkparm' are mutually exclusive");
++ break;
++ }
++ }
++ else if (is_attribute_p ("stackext", name))
++ {
++ if (lookup_attribute ("interrupt", TYPE_ATTRIBUTES(nnn)))
++ {
++ error ("`stackext' and `interrupt' are mutually exclusive");
++ break;
++ }
++ }
++ else if (is_attribute_p ("saveds", name))
++ {
++ }
++ }
++ else
++ {
++ warning (OPT_Wattributes, "`%s' attribute only applies to functions",
++ IDENTIFIER_POINTER(name));
++ }
++ return NULL_TREE;
++ } while (0);
++ // error case
++ *no_add_attrs = true;
++ return NULL_TREE;
++}
++
++
++extern bool
++m68k_rtx_costs (rtx, machine_mode, int, int, int *, bool);
++
++bool
++amigaos_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno,
++ int *total, bool speed)
++{
++// printf("outer: %d, opno: %d", outer_code, opno); fflush(stdout);
++// debug_rtx(x);
++ bool r = m68k_rtx_costs (x, mode, outer_code, opno, total, speed);
++ *total *= 4;
++ return r;
++}
++
++
+diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h
+new file mode 100755
+index 000000000000..1a33225ab60f
+--- /dev/null
++++ gcc/config/m68k/amigaos.h
+@@ -0,0 +1,490 @@
++/* Configuration for GNU C-compiler for m68k Amiga, running AmigaOS.
++ Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2003
++ Free Software Foundation, Inc.
++ Contributed by Markus M. Wild (wild@amiga.physik.unizh.ch).
++ Heavily modified by Kamil Iskra (iskra@student.uci.agh.edu.pl).
++
++
++This file is part of GCC.
++
++GCC 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.
++
++GCC 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 GCC; see the file COPYING. If not, write to
++the Free Software Foundation, 59 Temple Place - Suite 330,
++Boston, MA 02111-1307, USA. */
++
++#ifndef TARGET_AMIGAOS
++#define TARGET_AMIGAOS 1
++#endif
++
++#if 0
++/* The function name __transfer_from_trampoline is not actually used.
++ The function definition just permits use of asm with operands"
++ (though the operand list is empty). */
++
++#undef TRANSFER_FROM_TRAMPOLINE
++
++/* Call __flush_cache() after building the trampoline: it will call
++ an appropriate OS cache-clearing routine. */
++
++#undef FINALIZE_TRAMPOLINE
++#define FINALIZE_TRAMPOLINE(TRAMP) \
++ emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__flush_cache"), \
++ 0, VOIDmode, 2, (TRAMP), Pmode, \
++ GEN_INT (TRAMPOLINE_SIZE), SImode)
++
++#endif
++
++/* Compile using the first 'm68k_regparm' data, address and float
++ registers for arguments passing. */
++/*#define SUBTARGET_OPTIONS { "regparm=", &m68k_regparm_string, \
++ N_("Use this register count to pass arguments"), 0},*/
++
++
++/* Nonzero if we need to generate special stack-allocating insns.
++ On most systems they are not needed.
++ When they are needed, also define ALTERNATE_ALLOCATE_STACK (see m68k.md)
++ to perform the necessary actions. */
++//#undef TARGET_ALTERNATE_ALLOCATE_STACK
++//#define TARGET_ALTERNATE_ALLOCATE_STACK 0
++
++
++/* Compile with stack extension. */
++
++#define MASK_STACKEXTEND 0x40000000 /* 1 << 30 */
++#define TARGET_STACKEXTEND (((target_flags & MASK_STACKEXTEND) \
++ && !lookup_attribute ("interrupt", \
++ TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))) \
++ || lookup_attribute ("stackext", \
++ TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
++
++///* Compile with stack checking. */
++//
++#define MASK_STACKCHECK 0x20000000 /* 1 << 29 */
++#define TARGET_STACKCHECK ((target_flags & MASK_STACKCHECK) \
++ && !(target_flags & MASK_STACKEXTEND) \
++ && !lookup_attribute ("interrupt", \
++ TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))) \
++ && !lookup_attribute ("stackext", \
++ TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
++
++/* Compile with a4 restoring in public functions. */
++
++#define MASK_RESTORE_A4 0x10000000 /* 1 << 28 */
++#define TARGET_RESTORE_A4 \
++ ((target_flags & MASK_RESTORE_A4) && TREE_PUBLIC (current_function_decl))
++
++/* Compile with a4 restoring in all functions. */
++
++#define MASK_ALWAYS_RESTORE_A4 0x8000000 /* 1 << 27 */
++#define TARGET_ALWAYS_RESTORE_A4 (target_flags & MASK_ALWAYS_RESTORE_A4)
++
++/* Provide a dummy entry for the '-msmall-code' switch. This is used by
++ the assembler and '*_SPEC'. */
++
++#undef SUBTARGET_SWITCHES
++#define SUBTARGET_SWITCHES \
++ { "small-code", 0, \
++ "" /* Undocumented. */ }, \
++ { "stackcheck", MASK_STACKCHECK, \
++ N_("Generate stack-check code") }, \
++ { "no-stackcheck", - MASK_STACKCHECK, \
++ N_("Do not generate stack-check code") }, \
++ { "stackextend", MASK_STACKEXTEND, \
++ N_("Generate stack-extension code") }, \
++ { "no-stackextend", - MASK_STACKEXTEND, \
++ N_("Do not generate stack-extension code") }, \
++ { "fixedstack", - (MASK_STACKCHECK|MASK_STACKEXTEND), \
++ N_("Do not generate stack-check/stack-extension code") }, \
++ { "restore-a4", MASK_RESTORE_A4, \
++ N_("Restore a4 in public functions") }, \
++ { "no-restore-a4", - MASK_RESTORE_A4, \
++ N_("Do not restore a4 in public functions") }, \
++ { "always-restore-a4", MASK_ALWAYS_RESTORE_A4, \
++ N_("Restore a4 in all functions") }, \
++ { "no-always-restore-a4", - MASK_ALWAYS_RESTORE_A4, \
++ N_("Do not restore a4 in all functions") }
++
++#if 0
++/* Various ABI issues. */
++
++/* This is (almost;-) BSD, so it wants DBX format. */
++#undef DBX_DEBUGGING_INFO
++#define DBX_DEBUGGING_INFO
++
++/* GDB goes mad if it sees the function end marker. */
++
++#define NO_DBX_FUNCTION_END 1
++
++/* Allow folding division by zero. */
++
++#define REAL_INFINITY
++
++/* Don't try using XFmode since we don't have appropriate runtime software
++ support. */
++#undef LONG_DOUBLE_TYPE_SIZE
++#define LONG_DOUBLE_TYPE_SIZE 64
++
++/* We use A4 for the PIC pointer, not A5, which is the framepointer. */
++
++#undef PIC_OFFSET_TABLE_REGNUM
++#define PIC_OFFSET_TABLE_REGNUM (flag_pic ? 12 : INVALID_REGNUM)
++
++#undef PIC_REG
++#define PIC_REG 12
++
++/* Use A5 as framepointer instead of A6, since the AmigaOS ABI requires A6
++ to be used as a shared library base pointer in direct library calls. */
++
++#undef FRAME_POINTER_REGNUM
++#define FRAME_POINTER_REGNUM 13
++
++#undef M68K_REGNAME
++#define M68K_REGNAME(r) ( \
++ ( ((r) == FRAME_POINTER_REGNUM) \
++ && frame_pointer_needed) ? \
++ M68K_FP_REG_NAME : reg_names[(r)])
++
++
++/* The AmigaOS ABI does not define how structures should be returned, so,
++ contrary to 'm68k.h', we prefer a multithread-safe solution. */
++
++#undef PCC_STATIC_STRUCT_RETURN
++
++/* Setup a default shell return value for those (gazillion..) programs that
++ (inspite of ANSI-C) declare main() to be void (or even VOID...) and thus
++ cause the shell to randomly caugh upon executing such programs (contrary
++ to Unix, AmigaOS scripts are terminated with an error if a program returns
++ with an error code above the `error' or even `failure' level
++ (which is configurable with the FAILAT command)). */
++
++//+2004-06-24 Ulrich Weigand <uweigand@de.ibm.com>
++//+
++//+ * c-decl.c (finish_function): Do not check for DEFAULT_MAIN_RETURN.
++//+ * system.h (DEFAULT_MAIN_RETURN): Poison.
++//+ * doc/tm.texi (DEFAULT_MAIN_RETURN): Remove documentation.
++//+
++
++//poison VAR
++//#define DEFAULT_MAIN_RETURN c_expand_return (integer_zero_node)
++
++#undef WCHAR_TYPE
++#define WCHAR_TYPE "unsigned int"
++
++/* XXX: section support */
++#if 0
++/* Support sections in chip memory, currently '.datachip' only. */
++#undef TARGET_ASM_NAMED_SECTION
++#define TARGET_ASM_NAMED_SECTION amiga_named_section
++
++/* We define TARGET_ASM_NAMED_SECTION, but we don't support arbitrary sections,
++ including '.gcc_except_table', so we emulate the standard behaviour. */
++#undef TARGET_ASM_EXCEPTION_SECTION
++#define TARGET_ASM_EXCEPTION_SECTION amiga_exception_section
++
++#undef TARGET_ASM_EH_FRAME_SECTION
++#define TARGET_ASM_EH_FRAME_SECTION amiga_eh_frame_section
++#endif
++
++/* Use sjlj exceptions because dwarf work only on elf targets */
++#undef DWARF2_UNWIND_INFO
++#define DWARF2_UNWIND_INFO 0
++
++
++/* This is how to output an assembler line that says to advance the
++ location counter to a multiple of 2**LOG bytes. */
++
++#ifndef ALIGN_ASM_OP
++#define ALIGN_ASM_OP "\t.align\t"
++#endif
++
++/* GAS supports alignment up to 32768 bytes. */
++#undef ASM_OUTPUT_ALIGN
++#define ASM_OUTPUT_ALIGN(FILE, LOG) \
++do \
++ { \
++ if ((LOG) == 1) \
++ fprintf ((FILE), "\t.even\n"); \
++ else \
++ fprintf ((FILE), "\t.align %d\n", (LOG)); \
++ } \
++while (0)
++
++/* Baserel support. */
++
++/* Given that symbolic_operand(X), return TRUE if no special
++ base relative relocation is necessary */
++
++#define LEGITIMATE_BASEREL_OPERAND_P(X) \
++ (flag_pic >= 3 && read_only_operand (X))
++
++#undef LEGITIMATE_PIC_OPERAND_P
++#define LEGITIMATE_PIC_OPERAND_P(X) \
++ (! symbolic_operand (X, VOIDmode) || LEGITIMATE_BASEREL_OPERAND_P (X))
++
++/* Define this macro if references to a symbol must be treated
++ differently depending on something about the variable or
++ function named by the symbol (such as what section it is in).
++
++ The macro definition, if any, is executed immediately after the
++ rtl for DECL or other node is created.
++ The value of the rtl will be a `mem' whose address is a
++ `symbol_ref'.
++
++ The usual thing for this macro to do is to a flag in the
++ `symbol_ref' (such as `SYMBOL_REF_FLAG') or to store a modified
++ name string in the `symbol_ref' (if one bit is not enough
++ information).
++
++ On the Amiga we use this to indicate if references to a symbol should be
++ absolute or base relative. */
++
++#undef TARGET_ENCODE_SECTION_INFO
++#define TARGET_ENCODE_SECTION_INFO amigaos_encode_section_info
++
++#define LIBCALL_ENCODE_SECTION_INFO(FUN) \
++do \
++ { \
++ if (flag_pic >= 3) \
++ SYMBOL_REF_FLAG (FUN) = 1; \
++ } \
++while (0)
++
++/* Select and switch to a section for EXP. */
++
++//#undef TARGET_ASM_SELECT_SECTION
++//#define TARGET_ASM_SELECT_SECTION amigaos_select_section
++
++/* Preserve A4 for baserel code if necessary. */
++
++#define EXTRA_SAVE_REG(REGNO) \
++do { \
++ if (flag_pic && flag_pic >= 3 && REGNO == PIC_OFFSET_TABLE_REGNUM \
++ && amigaos_restore_a4()) \
++ return true; \
++} while (0)
++
++/* Predicate for ALTERNATE_PIC_SETUP. */
++
++#define HAVE_ALTERNATE_PIC_SETUP (flag_pic >= 3)
++
++/* Make a4 point at data hunk. */
++
++#define ALTERNATE_PIC_SETUP(STREAM) \
++ (amigaos_alternate_pic_setup (STREAM))
++
++/* Attribute support. */
++
++/* Generate the test of d0 before return to set cc register in 'interrupt'
++ function. */
++
++#define EPILOGUE_END_HOOK(STREAM) \
++do \
++ { \
++ if (lookup_attribute ("interrupt", \
++ TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))) \
++ asm_fprintf ((STREAM), "\ttstl %Rd0\n"); \
++ } \
++while (0)
++
++
++/* Stack checking and automatic extension support. */
++
++#define PROLOGUE_BEGIN_HOOK(STREAM, FSIZE) \
++ (amigaos_prologue_begin_hook ((STREAM), (FSIZE)))
++
++#define HAVE_ALTERNATE_FRAME_SETUP_F(FSIZE) TARGET_STACKEXTEND
++
++#define ALTERNATE_FRAME_SETUP_F(STREAM, FSIZE) \
++ (amigaos_alternate_frame_setup_f ((STREAM), (FSIZE)))
++
++#define HAVE_ALTERNATE_FRAME_SETUP(FSIZE) TARGET_STACKEXTEND
++
++#define ALTERNATE_FRAME_SETUP(STREAM, FSIZE) \
++ (amigaos_alternate_frame_setup ((STREAM), (FSIZE)))
++
++#define HAVE_ALTERNATE_FRAME_DESTR_F(FSIZE) \
++ (TARGET_STACKEXTEND && current_function_calls_alloca)
++
++#define ALTERNATE_FRAME_DESTR_F(STREAM, FSIZE) \
++ (asm_fprintf ((STREAM), "\tjra %U__unlk_a5_rts\n"))
++
++#define HAVE_ALTERNATE_RETURN \
++ (TARGET_STACKEXTEND && frame_pointer_needed && \
++ current_function_calls_alloca)
++
++#define ALTERNATE_RETURN(STREAM)
++
++#if 0
++#define HAVE_restore_stack_nonlocal TARGET_STACKEXTEND
++#define gen_restore_stack_nonlocal gen_stack_cleanup_call
++
++#define HAVE_restore_stack_function TARGET_STACKEXTEND
++#define gen_restore_stack_function gen_stack_cleanup_call
++
++#define HAVE_restore_stack_block TARGET_STACKEXTEND
++#define gen_restore_stack_block gen_stack_cleanup_call
++
++#undef TARGET_ALTERNATE_ALLOCATE_STACK
++#define TARGET_ALTERNATE_ALLOCATE_STACK 1
++
++#define ALTERNATE_ALLOCATE_STACK(OPERANDS) \
++do \
++ { \
++ amigaos_alternate_allocate_stack (OPERANDS); \
++ DONE; \
++ } \
++while (0)
++#endif
++
++/* begin-GG-local: dynamic libraries */
++
++extern int amigaos_do_collecting (void);
++extern void amigaos_gccopts_hook (const char *);
++extern void amigaos_libname_hook (const char* arg);
++extern void amigaos_collect2_cleanup (void);
++extern void amigaos_prelink_hook (const char **, int *);
++extern void amigaos_postlink_hook (const char *);
++
++/* This macro is used to check if all collect2 facilities should be used.
++ We need a few special ones, like stripping after linking. */
++
++#define DO_COLLECTING (do_collecting || amigaos_do_collecting())
++#define COLLECT2_POSTLINK_HOOK(OUTPUT_FILE) amigaos_postlink_hook(OUTPUT_FILE) //new
++
++/* This macro is called in collect2 for every GCC argument name.
++ ARG is a part of commandline (without '\0' at the end). */
++
++#define COLLECT2_GCC_OPTIONS_HOOK(ARG) amigaos_gccopts_hook(ARG)
++
++/* This macro is called in collect2 for every ld's "-l" or "*.o" or "*.a"
++ argument. ARG is a complete argument, with '\0' at the end. */
++
++#define COLLECT2_LIBNAME_HOOK(ARG) amigaos_libname_hook(ARG)
++
++/* This macro is called at collect2 exit, to clean everything up. */
++
++#define COLLECT2_EXTRA_CLEANUP amigaos_collect2_cleanup
++
++/* This macro is called just before the first linker invocation.
++ LD1_ARGV is "char** argv", which will be passed to "ld". STRIP is an
++ *address* of "strip_flag" variable. */
++
++#define COLLECT2_PRELINK_HOOK(LD1_ARGV, STRIP) \
++amigaos_prelink_hook((const char **)(LD1_ARGV), (STRIP))
++
++/* This macro is called just after the first linker invocation, in place of
++ "nm" and "ldd". OUTPUT_FILE is the executable's filename. */
++
++#define COLLECT2_POSTLINK_HOOK(OUTPUT_FILE) amigaos_postlink_hook(OUTPUT_FILE)
++/* end-GG-local */
++
++#endif
++
++/* begin-GG-local: explicit register specification for parameters */
++
++/* Note: this is an extension of m68k_args */
++
++
++/* A C type for declaring a variable that is used as the first
++ argument of `FUNCTION_ARG' and other related values. */
++/* Max. number of data, address and float registers to be used for passing
++ integer, pointer and float arguments when TARGET_REGPARM.
++ It's 4, so d0-d3, a0-a3 and fp0-fp3 can be used. */
++#undef AMIGAOS_MAX_REGPARM
++#define AMIGAOS_MAX_REGPARM 4
++
++/* The default number of data, address and float registers to use when
++ user specified '-mregparm' switch, not '-mregparm=<value>' option. */
++#undef AMIGAOS_DEFAULT_REGPARM
++#define AMIGAOS_DEFAULT_REGPARM 2
++
++
++#undef CLASS_MAX_NREGS
++#define CLASS_MAX_NREGS(CLASS, MODE) \
++ ((CLASS) == FP_REGS ? GET_MODE_NUNITS (MODE) \
++ : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
++
++/* 1 if N is a possible register number for function argument passing. */
++#undef FUNCTION_ARG_REGNO_P
++#define FUNCTION_ARG_REGNO_P(N) \
++ ((((int)N) >= 0 && (N) < AMIGAOS_MAX_REGPARM) \
++ || ((N) >= 8 && (N) < 8 + AMIGAOS_MAX_REGPARM) \
++ || (TARGET_68881 && (N) >= 16 && (N) < 16 + AMIGAOS_MAX_REGPARM))
++
++/*
++ On the m68k, this is a structure:
++ num_of_regs: number of data, address and float registers to use for
++ arguments passing (if it's 2, than pass arguments in d0, d1, a0, a1,
++ fp0 and fp1). 0 - pass everything on stack. vararg calls are
++ always passed entirely on stack.
++ regs_already_used: bitmask of the already used registers.
++ last_arg_reg - register number of the most recently passed argument.
++ -1 if passed on stack.
++ last_arg_len - number of registers used by the most recently passed
++ argument.
++*/
++
++extern void amigaos_init_cumulative_args (CUMULATIVE_ARGS *cum, tree);
++extern void amigaos_function_arg_advance (cumulative_args_t, machine_mode, const_tree, bool);
++extern rtx amigaos_function_arg (cumulative_args_t, machine_mode, const_tree, bool);
++extern cumulative_args_t amigaos_pack_cumulative_args (CUMULATIVE_ARGS *);
++extern int amigaos_comp_type_attributes (const_tree, const_tree);
++extern tree amigaos_handle_type_attribute(tree *, tree, tree, int, bool*);
++
++/* Update the data in CUM to advance over an argument
++ of mode MODE and data type TYPE.
++ (TYPE is null for libcalls where that information may not be available.) */
++
++#undef TARGET_FUNCTION_ARG_ADVANCE
++#define TARGET_FUNCTION_ARG_ADVANCE amigaos_function_arg_advance
++
++/* A C expression that controls whether a function argument is passed
++ in a register, and which register. */
++
++#undef TARGET_FUNCTION_ARG
++#define TARGET_FUNCTION_ARG amigaos_function_arg
++
++#undef TARGET_PACK_CUMULATIVE_ARGS
++#define TARGET_PACK_CUMULATIVE_ARGS(CUM) \
++ (amigaos_pack_cumulative_args(&(CUM)))
++
++#undef TARGET_COMP_TYPE_ATTRIBUTES
++#define TARGET_COMP_TYPE_ATTRIBUTES amigaos_comp_type_attributes
++
++
++/* end-GG-local */
++
++#undef SUBTARGET_OVERRIDE_OPTIONS
++#define SUBTARGET_OVERRIDE_OPTIONS \
++do \
++ { \
++ if (!TARGET_68020 && flag_pic==4) \
++ error ("-fbaserel32 is not supported on the 68000 or 68010\n"); \
++ if (amigaos_regparm > 0 && amigaos_regparm > AMIGAOS_MAX_REGPARM) \
++ error ("-mregparm=x with 1 <= x <= %d\n", AMIGAOS_MAX_REGPARM); \
++ } \
++while (0)
++
++/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
++ affects_type_identity } */
++#define SUBTARGET_ATTRIBUTES \
++ { "regparm", 1, 1, true, false, false, amigaos_handle_type_attribute,\
++ false },
++
++#define GOT_SYMBOL_NAME ""
++
++#undef TARGET_RTX_COSTS
++#define TARGET_RTX_COSTS amigaos_rtx_costs
++bool
++amigaos_rtx_costs (rtx, machine_mode, int, int, int *, bool);
++
+diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt
+new file mode 100755
+index 000000000000..a9bc80c4f5b6
+--- /dev/null
++++ gcc/config/m68k/amigaos.opt
+@@ -0,0 +1,13 @@
++
++mregparm=
++Target RejectNegative Var(amigaos_regparm) Joined UInteger
++Pass arguments through registers.
++
++noixemul
++Target RejectNegative
++Do not use ixemul.library - use libnix instead to link
++
++msmall-code
++Target RejectNegative
++small code model
++
+diff --git a/gcc/config/m68k/host-amigaos.c b/gcc/config/m68k/host-amigaos.c
+new file mode 100755
+index 000000000000..8c72d516a378
+--- /dev/null
++++ gcc/config/m68k/host-amigaos.c
+@@ -0,0 +1,42 @@
++/* AmigaOS/m68k host-specific hook definitions.
++ Copyright (C) 2003 Free Software Foundation, Inc.
++
++This file is part of GCC.
++
++GCC 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.
++
++GCC 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 GCC; see the file COPYING. If not, write to the Free
++Software Foundation, 59 Temple Place - Suite 330, Boston, MA
++02111-1307, USA. */
++
++
++#include "config.h"
++#include "system.h"
++#include "coretypes.h"
++#include "hosthooks.h"
++#include "hosthooks-def.h"
++#include "toplev.h"
++
++static void * amigaos_m68k_gt_pch_get_address (size_t);
++
++/* Return the address of the PCH address space, if the PCH will fit in it. */
++
++static void *
++amigaos_m68k_gt_pch_get_address (size_t sz ATTRIBUTE_UNUSED)
++{
++ fatal_error ("PCH not supported\n");
++}
++
++#undef HOST_HOOKS_GT_PCH_GET_ADDRESS
++#define HOST_HOOKS_GT_PCH_GET_ADDRESS amigaos_m68k_gt_pch_get_address
++
++const struct host_hooks host_hooks = HOST_HOOKS_INITIALIZER;
+\ No newline at end of file
+diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
+index 03f474e1b63c..fe3a939e1530 100644
+--- gcc/config/m68k/m68k.c
++++ gcc/config/m68k/m68k.c
+@@ -166,7 +166,10 @@ static bool m68k_save_reg (unsigned int regno, bool interrupt_handler);
+ static bool m68k_ok_for_sibcall_p (tree, tree);
+ static bool m68k_tls_symbol_p (rtx);
+ static rtx m68k_legitimize_address (rtx, rtx, machine_mode);
+-static bool m68k_rtx_costs (rtx, machine_mode, int, int, int *, bool);
++#ifndef TARGET_AMIGAOS
++static
++#endif
++bool m68k_rtx_costs (rtx, machine_mode, int, int, int *, bool);
+ #if M68K_HONOR_TARGET_STRICT_ALIGNMENT
+ static bool m68k_return_in_memory (const_tree, const_tree);
+ #endif
+@@ -174,10 +177,12 @@ static void m68k_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
+ static void m68k_trampoline_init (rtx, tree, rtx);
+ static int m68k_return_pops_args (tree, tree, int);
+ static rtx m68k_delegitimize_address (rtx);
++#ifndef TARGET_AMIGA
+ static void m68k_function_arg_advance (cumulative_args_t, machine_mode,
+ const_tree, bool);
+ static rtx m68k_function_arg (cumulative_args_t, machine_mode,
+ const_tree, bool);
++#endif
+ static bool m68k_cannot_force_const_mem (machine_mode mode, rtx x);
+ static bool m68k_output_addr_const_extra (FILE *, rtx);
+ static void m68k_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
+@@ -322,6 +327,10 @@ static void m68k_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
+ #undef TARGET_ATOMIC_TEST_AND_SET_TRUEVAL
+ #define TARGET_ATOMIC_TEST_AND_SET_TRUEVAL 128
+
++#ifdef TARGET_AMIGA
++#include "amigaos.h"
++#endif
++
+ static const struct attribute_spec m68k_attribute_table[] =
+ {
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
+@@ -332,6 +341,9 @@ static const struct attribute_spec m68k_attribute_table[] =
+ m68k_handle_fndecl_attribute, false },
+ { "interrupt_thread", 0, 0, true, false, false,
+ m68k_handle_fndecl_attribute, false },
++#ifdef SUBTARGET_ATTRIBUTES
++ SUBTARGET_ATTRIBUTES
++#endif
+ { NULL, 0, 0, false, false, false, NULL, false }
+ };
+
+@@ -1419,6 +1431,7 @@ m68k_ok_for_sibcall_p (tree decl, tree exp)
+ return false;
+ }
+
++#ifndef TARGET_AMIGA
+ /* On the m68k all args are always pushed. */
+
+ static rtx
+@@ -1440,6 +1453,7 @@ m68k_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
+ ? (GET_MODE_SIZE (mode) + 3) & ~3
+ : (int_size_in_bytes (type) + 3) & ~3);
+ }
++#endif
+
+ /* Convert X to a legitimate function call memory reference and return the
+ result. */
+@@ -2172,6 +2186,8 @@ m68k_get_gp (void)
+ if (pic_offset_table_rtx == NULL_RTX)
+ pic_offset_table_rtx = gen_rtx_REG (Pmode, PIC_REG);
+
++// debug_rtx(pic_offset_table_rtx);
++
+ crtl->uses_pic_offset_table = 1;
+
+ return pic_offset_table_rtx;
+@@ -2442,9 +2458,9 @@ legitimize_pic_address (rtx orig, machine_mode mode ATTRIBUTE_UNUSED,
+ if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
+ {
+ gcc_assert (reg);
+-
+ pic_ref = m68k_wrap_symbol_into_got_ref (orig, RELOC_GOT, reg);
+ pic_ref = m68k_move_to_reg (pic_ref, orig, reg);
++// debug_rtx(pic_ref);
+ }
+ else if (GET_CODE (orig) == CONST)
+ {
+@@ -2787,7 +2803,10 @@ const_int_cost (HOST_WIDE_INT i)
+ }
+ }
+
+-static bool
++#ifndef TARGET_AMIGAOS
++static
++#endif
++bool
+ m68k_rtx_costs (rtx x, machine_mode mode, int outer_code,
+ int opno ATTRIBUTE_UNUSED,
+ int *total, bool speed ATTRIBUTE_UNUSED)
+@@ -4424,6 +4443,7 @@ floating_exact_log2 (rtx x)
+ void
+ print_operand (FILE *file, rtx op, int letter)
+ {
++// printf("letter: %c\n", letter);
+ if (letter == '.')
+ {
+ if (MOTOROLA)
+@@ -4521,7 +4541,9 @@ m68k_get_reloc_decoration (enum m68k_reloc reloc)
+ switch (reloc)
+ {
+ case RELOC_GOT:
+- if (MOTOROLA)
++ if (TARGET_AMIGAOS)
++ return "";
++ else if (MOTOROLA)
+ {
+ if (flag_pic == 1 && TARGET_68020)
+ return "@GOT.w";
+diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h
+index 2aa858fa23b5..74d5aa042059 100644
+--- gcc/config/m68k/m68k.h
++++ gcc/config/m68k/m68k.h
+@@ -971,3 +971,8 @@ extern int m68k_sched_address_bypass_p (rtx_insn *, rtx_insn *);
+ extern int m68k_sched_indexed_address_bypass_p (rtx_insn *, rtx_insn *);
+
+ #define CPU_UNITS_QUERY 1
++
++#if 1
++extern void default_stabs_asm_out_constructor (rtx, int);
++extern void default_stabs_asm_out_destructor (rtx, int);
++#endif
+diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
+index ec37bd76f55f..f5b63f43c372 100644
+--- gcc/config/m68k/m68k.md
++++ gcc/config/m68k/m68k.md
+@@ -7092,6 +7092,8 @@
+ operands[1] = gen_rtx_REG (Pmode, PIC_REG);
+ return MOTOROLA ? "move.l %?(%1),%0" : "movel %1@(%?), %0";
+ }
++ else if (TARGET_AMIGAOS)
++ return "lea (%%pc, __GLOBAL_OFFSET_TABLE_), %0";
+ else if (MOTOROLA)
+ {
+ if (TARGET_COLDFIRE)
+diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h
+new file mode 100755
+index 000000000000..0ce599138c7d
+--- /dev/null
++++ gcc/config/m68k/m68kamigaos.h
+@@ -0,0 +1,424 @@
++/* m68kelf support, derived from m68kv4.h */
++
++/* Target definitions for GNU compiler for mc680x0 running AmigaOs
++ Copyright (C) 1991-2016 Free Software Foundation, Inc.
++
++ Written by Ron Guilmette (rfg@netcom.com) and Fred Fish (fnf@cygnus.com).
++
++This file is part of GCC.
++
++GCC 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 3, or (at your option)
++any later version.
++
++GCC 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 GCC; see the file COPYING3. If not see
++<http://www.gnu.org/licenses/>. */
++
++#ifndef TARGET_AMIGA
++#define TARGET_AMIGA 1
++#endif
++
++#ifndef SWBEG_ASM_OP
++#define SWBEG_ASM_OP "\t.swbeg\t"
++#endif
++
++#undef PIC_REG
++#define PIC_REG 12
++
++#undef FRAME_POINTER_REGNUM
++#define FRAME_POINTER_REGNUM 13
++
++#undef M68K_REGNAME
++#define M68K_REGNAME(r) ( \
++ ( ((r) == FRAME_POINTER_REGNUM) \
++ && frame_pointer_needed) ? \
++ M68K_FP_REG_NAME : reg_names[(r)])
++
++
++
++/* Here are three prefixes that are used by asm_fprintf to
++ facilitate customization for alternate assembler syntaxes.
++ Machines with no likelihood of an alternate syntax need not
++ define these and need not use asm_fprintf. */
++
++/* The prefix for register names. Note that REGISTER_NAMES
++ is supposed to include this prefix. Also note that this is NOT an
++ fprintf format string, it is a literal string */
++
++#undef REGISTER_PREFIX
++#define REGISTER_PREFIX ""
++
++/* The prefix for local (compiler generated) labels.
++ These labels will not appear in the symbol table. */
++
++#undef LOCAL_LABEL_PREFIX
++#define LOCAL_LABEL_PREFIX "."
++
++/* The prefix to add to user-visible assembler symbols. */
++
++#undef USER_LABEL_PREFIX
++#define USER_LABEL_PREFIX "_"
++
++/* config/m68k.md has an explicit reference to the program counter,
++ prefix this by the register prefix. */
++
++#define ASM_RETURN_CASE_JUMP \
++ do { \
++ return "jmp %%pc@(2,%0:w)"; \
++ } while (0)
++
++/* This is how to output an assembler line that says to advance the
++ location counter to a multiple of 2**LOG bytes. */
++
++#ifndef ALIGN_ASM_OP
++#define ALIGN_ASM_OP "\t.align\t"
++#endif
++
++#undef ASM_OUTPUT_ALIGN
++#define ASM_OUTPUT_ALIGN(FILE,LOG) \
++do { \
++ if ((LOG) > 0) \
++ fprintf ((FILE), "%s%u\n", ALIGN_ASM_OP, 1 << (LOG)); \
++} while (0)
++
++/* Register in which address to store a structure value is passed to a
++ function. The default in m68k.h is a1. For m68k/SVR4 it is a0. */
++
++#undef M68K_STRUCT_VALUE_REGNUM
++#define M68K_STRUCT_VALUE_REGNUM A0_REG
++
++/* The static chain regnum defaults to a0, but we use that for
++ structure return, so have to use a1 for the static chain. */
++
++#undef STATIC_CHAIN_REGNUM
++#define STATIC_CHAIN_REGNUM A1_REG
++#undef M68K_STATIC_CHAIN_REG_NAME
++#define M68K_STATIC_CHAIN_REG_NAME REGISTER_PREFIX "a1"
++
++#define ASM_COMMENT_START "|"
++
++/* Define how the m68k registers should be numbered for Dwarf output.
++ The numbering provided here should be compatible with the native
++ SVR4 SDB debugger in the m68k/SVR4 reference port, where d0-d7
++ are 0-7, a0-a8 are 8-15, and fp0-fp7 are 16-23. */
++
++#undef DBX_REGISTER_NUMBER
++#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
++
++#if 0
++/* SVR4 m68k assembler is bitching on the `comm i,1,1' which askes for
++ 1 byte alignment. Don't generate alignment for COMMON seems to be
++ safer until we the assembler is fixed. */
++#undef ASM_OUTPUT_ALIGNED_COMMON
++/* Same problem with this one. */
++#undef ASM_OUTPUT_ALIGNED_LOCAL
++#endif
++
++#undef ASM_OUTPUT_COMMON
++#undef ASM_OUTPUT_LOCAL
++#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
++( fputs (".comm ", (FILE)), \
++ assemble_name ((FILE), (NAME)), \
++ fprintf ((FILE), ",%u\n", (int)(SIZE)))
++
++#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
++( fputs (".lcomm ", (FILE)), \
++ assemble_name ((FILE), (NAME)), \
++ fprintf ((FILE), ",%u\n", (int)(SIZE)))
++
++/* Currently, JUMP_TABLES_IN_TEXT_SECTION must be defined in order to
++ keep switch tables in the text section. */
++
++#define JUMP_TABLES_IN_TEXT_SECTION 1
++
++/* In m68k svr4, using swbeg is the standard way to do switch
++ table. */
++#undef ASM_OUTPUT_BEFORE_CASE_LABEL
++#define ASM_OUTPUT_BEFORE_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \
++ fprintf ((FILE), "%s&%d\n", SWBEG_ASM_OP, XVECLEN (PATTERN (TABLE), 1));
++/* end of stuff from m68kv4.h */
++
++#undef ENDFILE_SPEC
++#define ENDFILE_SPEC "crtend.o%s"
++
++#undef STARTFILE_SPEC
++#define STARTFILE_SPEC "crtbegin.o%s"
++
++#ifndef BSS_SECTION_ASM_OP
++#define BSS_SECTION_ASM_OP "\t.section\t.bss"
++#endif
++
++#ifndef ASM_OUTPUT_ALIGNED_BSS
++#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
++ asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
++#endif
++
++
++/* Specs, switches. */
++
++/* amiga/amigaos are the new "standard" defines for the Amiga.
++ MCH_AMIGA, AMIGA, __chip etc. are used in other compilers and are
++ provided for compatibility reasons.
++ When creating shared libraries, use different 'errno'. */
++
++
++
++#undef TARGET_OS_CPP_BUILTINS
++#define TARGET_OS_CPP_BUILTINS() \
++ do \
++ { \
++ builtin_define ("__chip=__attribute__((__chip__))"); \
++ builtin_define ("__saveds=__attribute__((__saveds__))"); \
++ builtin_define ("__interrupt=__attribute__((__interrupt__))"); \
++ builtin_define ("__stackext=__attribute__((__stackext__))"); \
++ builtin_define ("__regargs_x=__attribute__((regparm))"); \
++ builtin_define ("__stdargs_x=__attribute__((stkparm))"); \
++ builtin_define ("__aligned=__attribute__((__aligned__(4)))"); \
++ builtin_define_std ("amiga"); \
++ builtin_define_std ("amigaos"); \
++ builtin_define_std ("AMIGA"); \
++ builtin_define_std ("MCH_AMIGA"); \
++ builtin_assert ("system=amigaos"); \
++ } \
++ while (0)
++
++#if 0
++if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
++ builtin_define ("errno=(*ixemul_errno)"); \
++
++#endif
++
++/* Inform the program which CPU we compile for. */
++
++//#undef TARGET_CPU_CPP_BUILTINS
++/*
++ use --with-cpu=mc68040 etc.. instead on config. code was after #define TARGET_CPU_CPP_BUILTINS()
++ if (TARGET_68040_ONLY) \
++ { \
++ if (TARGET_68060) \
++ builtin_define_std ("mc68060"); \
++ else \
++ builtin_define_std ("mc68040"); \
++ } \
++ else if (TARGET_68030 && !TARGET_68040) \
++ builtin_define_std ("mc68030"); \
++ else if (TARGET_68020) \
++ builtin_define_std ("mc68020"); \
++ builtin_define_std ("mc68000"); \
++*/
++/*
++#define TARGET_CPU_CPP_BUILTINS() \
++ do \
++ { \
++ builtin_define_std ("mc68040"); \
++ if (flag_pic > 2) \
++ { \
++ builtin_define ("__pic__"); \
++ if (flag_pic > 3) \
++ builtin_define ("__PIC__"); \
++ } \
++ builtin_assert ("cpu=m68k"); \
++ builtin_assert ("machine=m68k"); \
++ } \
++ while (0)
++*/
++/* Define __HAVE_68881__ in preprocessor according to the -m flags.
++ This will control the use of inline 68881 insns in certain macros.
++ Note: it should be set in TARGET_CPU_CPP_BUILTINS but TARGET_68881
++ isn't the same -m68881 since its also true for -m680[46]0 ...
++ Differentiate between libnix and ixemul. */
++
++#define CPP_SPEC \
++ "%{m68881:-D__HAVE_68881__} " \
++ "%{!ansi:" \
++ "%{m68020:-Dmc68020} " \
++ "%{mc68020:-Dmc68020} " \
++ "%{m68020-40:-Dmc68020} " \
++ "%{m68020-60:-Dmc68020} " \
++ "%{m68030:-Dmc68030} " \
++ "%{m68040:-Dmc68040} " \
++ "%{m68060:-Dmc68060}} " \
++ "%{m68020:-D__mc68020__ -D__mc68020} " \
++ "%{mc68020:-D__mc68020__ -D__mc68020} " \
++ "%{m68020-40:-D__mc68020__ -D__mc68020} " \
++ "%{m68020-60:-D__mc68020__ -D__mc68020} " \
++ "%{m68030:-D__mc68030__ -D__mc68030} " \
++ "%{m68040:-D__mc68040__ -D__mc68040} " \
++ "%{m68060:-D__mc68060__ -D__mc68060} " \
++ "%{noixemul:%{!ansi:%{!std=*:-Dlibnix}%{std=gnu*:-Dlibnix}} -D__libnix -D__libnix__} " \
++ "%{!noixemul:%{!ansi:%{!std=*:-Dixemul}%{std=gnu*:-Dixemul}} -D__ixemul -D__ixemul__}"
++
++/* Translate '-resident' to '-fbaserel' (they differ in linking stage only).
++ Don't put function addresses in registers for PC-relative code. */
++
++#define CC1_SPEC \
++ "%{resident:-fbaserel} " \
++ "%{resident32:-fbaserel32} " \
++ "%{msmall-code:-fno-function-cse}"
++
++/* Various -m flags require special flags to the assembler. */
++
++#undef ASM_SPEC
++#define ASM_SPEC \
++ "%(asm_cpu) %(asm_cpu_default) %{msmall-code:-sc}"
++
++#undef ASM_CPU_SPEC
++#define ASM_CPU_SPEC \
++ "%{m68000|mc68000:-m68010} " \
++ "%{m6802*|mc68020:-m68020} " \
++ "%{m68030} " \
++ "%{m68040} " \
++ "%{m68060}"
++
++#define ASM_CPU_DEFAULT_SPEC \
++ "%{!m680*:%{!mc680*:-m68040}}"
++
++/* If debugging, tell the linker to output amiga-hunk symbols *and* a BSD
++ compatible debug hunk.
++ Also, pass appropriate linker flavours depending on user-supplied
++ commandline options. */
++
++#define LINK_SPEC \
++ "%{noixemul:-fl libnix} " \
++ "%{resident*:-amiga-datadata-reloc} " \
++ "%{resident|fbaserel:-m amiga_bss -fl libb} " \
++ "%{resident32|fbaserel32:-m amiga_bss -fl libb32} " \
++ "%{g:-amiga-debug-hunk} " \
++ "%(link_cpu)"
++
++#define LINK_CPU_SPEC \
++ "%{m6802*|mc68020|m68030|m68040|m68060:-fl libm020} " \
++ "%{m68881:-fl libm881}"
++
++/* Choose the right startup file, depending on whether we use base relative
++ code, base relative code with automatic relocation (-resident), their
++ 32-bit versions, libnix, profiling or plain crt0.o. */
++
++#undef STARTFILE_SPEC
++#define STARTFILE_SPEC \
++ "%{!noixemul:" \
++ "%{fbaserel:%{!resident:bcrt0.o%s}}" \
++ "%{resident:rcrt0.o%s}" \
++ "%{fbaserel32:%{!resident32:lcrt0.o%s}}" \
++ "%{resident32:scrt0.o%s}" \
++ "%{!resident:%{!fbaserel:%{!resident32:%{!fbaserel32:" \
++ "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}}}}}" \
++ "%{noixemul:" \
++ "%{resident:libnix/nrcrt0.o%s} " \
++ "%{!resident:%{fbaserel:libnix/nbcrt0.o%s}%{!fbaserel:libnix/ncrt0.o%s}}}"
++
++#undef ENDFILE_SPEC
++#define ENDFILE_SPEC \
++ "%{noixemul:-lstubs}"
++
++/* put return values in FPU build in FP0 Reg */
++#undef FUNCTION_VALUE_REGNO_P
++#define FUNCTION_VALUE_REGNO_P(N) \
++ ((N) == D0_REG || (N) == A0_REG || (TARGET_68881 && (N) == FP0_REG))
++
++
++/* Automatically search libamiga.a for AmigaOS specific functions. Note
++ that we first search the standard C library to resolve as much as
++ possible from there, since it has names that are duplicated in libamiga.a
++ which we *don't* want from there. Then search libamiga.a for any calls
++ that were not generated inline, and finally search the standard C library
++ again to resolve any references that libamiga.a might have generated.
++ This may only be a temporary solution since it might be better to simply
++ remove the things from libamiga.a that should be pulled in from libc.a
++ instead, which would eliminate the first reference to libc.a. Note that
++ if we don't search it automatically, it is very easy for the user to try
++ to put in a -lamiga himself and get it in the wrong place, so that (for
++ example) calls like sprintf come from -lamiga rather than -lc. */
++
++#undef LIB_SPEC
++#define LIB_SPEC \
++ "%{!noixemul:" \
++ "%{p|pg:-lc_p}" \
++ "%{!p:%{!pg:-lc -lamiga -lc}}}" \
++ "%{noixemul:" \
++ "-lnixmain -lnix -lamiga %{mstackcheck|mstackextend:-lstack}}"
++
++/* This macro defines names of additional specifications to put in the specs
++ that can be used in various specifications like CC1_SPEC. Its definition
++ is an initializer with a subgrouping for each command option.
++
++ Each subgrouping contains a string constant, that defines the
++ specification name, and a string constant that used by the GCC driver
++ program.
++
++ Do not define this macro if it does not need to do anything. */
++#undef EXTRA_SPECS
++#define EXTRA_SPECS \
++ { "asm_cpu", ASM_CPU_SPEC }, \
++ { "asm_cpu_default", ASM_CPU_DEFAULT_SPEC }, \
++ { "link_cpu", LINK_CPU_SPEC }
++
++
++/* begin-GG-local: dynamic libraries */
++
++extern int amigaos_do_collecting (void);
++extern void amigaos_gccopts_hook (const char *);
++extern void amigaos_libname_hook (const char* arg);
++extern void amigaos_collect2_cleanup (void);
++extern void amigaos_prelink_hook (const char **, int *);
++extern void amigaos_postlink_hook (const char *);
++
++/* This macro is used to check if all collect2 facilities should be used.
++ We need a few special ones, like stripping after linking. */
++
++#define DO_COLLECTING (do_collecting || amigaos_do_collecting())
++
++/* This macro is called in collect2 for every GCC argument name.
++ ARG is a part of commandline (without '\0' at the end). */
++
++#define COLLECT2_GCC_OPTIONS_HOOK(ARG) amigaos_gccopts_hook(ARG)
++
++/* This macro is called in collect2 for every ld's "-l" or "*.o" or "*.a"
++ argument. ARG is a complete argument, with '\0' at the end. */
++
++#define COLLECT2_LIBNAME_HOOK(ARG) amigaos_libname_hook(ARG)
++
++/* This macro is called at collect2 exit, to clean everything up. */
++
++#define COLLECT2_EXTRA_CLEANUP amigaos_collect2_cleanup
++
++/* This macro is called just before the first linker invocation.
++ LD1_ARGV is "char** argv", which will be passed to "ld". STRIP is an
++ *address* of "strip_flag" variable. */
++
++#define COLLECT2_PRELINK_HOOK(LD1_ARGV, STRIP) \
++amigaos_prelink_hook((const char **)(LD1_ARGV), (STRIP))
++
++/* This macro is called just after the first linker invocation, in place of
++ "nm" and "ldd". OUTPUT_FILE is the executable's filename. */
++
++#define COLLECT2_POSTLINK_HOOK(OUTPUT_FILE) amigaos_postlink_hook(OUTPUT_FILE)
++/* end-GG-local */
++
++#undef MAX_OFILE_ALIGNMENT
++#define MAX_OFILE_ALIGNMENT ((1 << 15)*BITS_PER_UNIT)
++
++#if 0
++#undef INCLUDE_DEFAULTS
++#define INCLUDE_DEFAULTS \
++ { \
++ { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1, \
++ GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 0 }, \
++ { GCC_INCLUDE_DIR, "GCC", 0, 0 }, \
++ { CROSS_INCLUDE_DIR "/../../os-include", "GCC", 0, 0 }, \
++ { TOOL_INCLUDE_DIR "/../ndk/include", "GCC", 0, 0 }, \
++ { CROSS_INCLUDE_DIR, "GCC", 0, 0, 0 }, \
++ { 0, 0, 0, 0 } \
++ }
++#endif
++
++#undef FIXED_INCLUDE_DIR
++#define FIXED_INCLUDE_DIR CROSS_INCLUDE_DIR "/../../os-include"
++
+diff --git a/gcc/config/m68k/m68kemb.h b/gcc/config/m68k/m68kemb.h
+index 0d8d88c74ea9..29b3e194f12d 100644
+--- gcc/config/m68k/m68kemb.h
++++ gcc/config/m68k/m68kemb.h
+@@ -32,12 +32,14 @@
+ #define NEEDS_UNTYPED_CALL 1
+
+ /* Target OS builtins. */
++#ifndef TARGET_OS_CPP_BUILTINS
+ #define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__embedded__"); \
+ } \
+ while (0)
++#endif
+
+ /* Override the default LIB_SPEC from gcc.c. We don't currently support
+ profiling, or libg.a. */
+diff --git a/gcc/config/m68k/t-amigaos b/gcc/config/m68k/t-amigaos
+new file mode 100755
+index 000000000000..112d5daa06fb
+--- /dev/null
++++ gcc/config/m68k/t-amigaos
+@@ -0,0 +1,30 @@
++# Makefile fragment for AmigaOS target.
++
++# Extra object file linked to the cc1* executables.
++amigaos.o: $(srcdir)/config/m68k/amigaos.c $(CONFIG_H)
++ $(CXX) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
++
++# Additional target dependent options for compiling libgcc.a. This just
++# ensures that we don't compile libgcc* with anything other than a
++# fixed stack.
++
++#TARGET_LIBGCC2_CFLAGS = -mfixedstack
++
++# Support for building multiple version of libgcc.
++
++LIBGCC_MULTI = .; \
++ libb;@fbaserel \
++ libm020;@m68020 \
++ libb/libm020;@fbaserel@m68020 \
++ libb32/libm020;@fbaserel32@m68020
++
++### begin-GG-local: dynamic libraries
++# Extra objects that get compiled and linked to collect2
++
++EXTRA_COLLECT2_OBJS = amigacollect2.o
++
++# Build supplimentary AmigaOS target support file for collect2
++amigacollect2.o: amigacollect2.c
++ $(CXX) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
++ -DA2IXDIR_PREFIX=\"$(prefix)/share/a2ixlibrary\" $< $(OUTPUT_OPTION)
++### end-GG-local
+diff --git a/gcc/config/m68k/x-amigaos b/gcc/config/m68k/x-amigaos
+new file mode 100755
+index 000000000000..a8f60b80f9f4
+--- /dev/null
++++ gcc/config/m68k/x-amigaos
+@@ -0,0 +1,104 @@
++# Makefile fragment for AmigaOS host
++
++# Each compilation environment (Manx, Dice, GCC, SAS/C, etc) provides its
++# own equivalent of the UNIX /usr/include tree. For gcc, the standard headers
++# are in /gg/include and system specific headers are in /gg/os-include.
++# Use these paths for fixincludes.
++
++SYSTEM_HEADER_DIR = $(prefix)/include
++
++# Uncomment the following macro to get a resident GCC. We don't do it
++# by default, since we want to support users with mc68000.
++# WARNING! If you uncomment this, you MUST add the same flags to the
++# libiberty's Makefile (libiberty is now linked into GCC executables).
++
++#RESIDENT = -m68020 -resident32
++
++# Additional host flags that are not used when compiling with GCC_FOR_TARGET,
++# such as when compiling the libgcc* runtime archives. GCC uses stack
++# a lot, and since AmigaOS provides processes with a small, fixed size
++# stack, we have to generate code that will extend it whenever necessary.
++
++XCFLAGS = -mstackextend $(RESIDENT)
++
++# AmigaOS supports "AmigaGuide(R)" hypertext files. For GCC, these are
++# build with a custom "makeinfo".
++
++# Arrange for guides to be build with GCC, in the build directory.
++
++### begin-GG-local: gcc-amigaos
++#EXTRA_DOC_TARGETS = guide gcc-amigaos-doc
++### end-GG-local
++
++# Actually build guides
++
++guide:: doc/cpp.guide doc/gcc.guide doc/gccint.guide \
++ doc/gccinstall.guide doc/cppinternals.guide
++
++doc/cpp.guide: $(TEXI_CPP_FILES)
++doc/gcc.guide: $(TEXI_GCC_FILES)
++doc/gccint.guide: $(TEXI_GCCINT_FILES)
++doc/cppinternals.guide: $(TEXI_CPPINT_FILES)
++
++doc/%.guide: %.texi
++ if [ x$(BUILD_INFO) = xinfo ]; then \
++ $(MAKEINFO) --amiga $(MAKEINFOFLAGS) -I $(docdir) \
++ -I $(docdir)/include -o $@ $<; \
++ fi
++
++# Duplicate entry to handle renaming of gccinstall.guide
++doc/gccinstall.guide: $(TEXI_GCCINSTALL_FILES)
++ if [ x$(BUILD_INFO) = xinfo ]; then \
++ $(MAKEINFO) --amiga $(MAKEINFOFLAGS) -I $(docdir) \
++ -I $(docdir)/include -o $@ install.texi; \
++ fi
++
++# Arrange for guides to be installed with GCC.
++
++### begin-GG-local: gcc-amigaos
++#EXTRA_INSTALL_TARGETS = install-guide install-gcc-amigaos-doc
++### end-GG-local
++
++# Where the guide files go
++
++guidedir = $(prefix)/guide
++
++# Actually install guides.
++
++installdirs-guide:
++ $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(guidedir)
++
++install-guide: doc installdirs-guide \
++ $(DESTDIR)$(guidedir)/cpp.guide \
++ $(DESTDIR)$(guidedir)/gcc.guide \
++ $(DESTDIR)$(guidedir)/cppinternals.guide \
++ $(DESTDIR)$(guidedir)/gccinstall.guide \
++ $(DESTDIR)$(guidedir)/gccint.guide
++
++$(DESTDIR)$(guidedir)/%.guide: doc/%.guide installdirs-guide
++ rm -f $@
++ if [ -f $< ]; then \
++ for f in $(<)*; do \
++ realfile=`echo $$f | sed -e 's|.*/\([^/]*\)$$|\1|'`; \
++ $(INSTALL_DATA) $$f $(DESTDIR)$(guidedir)/$$realfile; \
++ chmod a-x $(DESTDIR)$(guidedir)/$$realfile; \
++ done; \
++ else true; fi
++
++### begin-GG-local: gcc-amigaos
++# Build and install gcc-amigaos.guide - documentation specific to the
++# AmigaOS port of GCC.
++
++gcc-amigaos-doc:: doc/gcc-amigaos.info doc/gcc-amigaos.guide
++
++doc/gcc-amigaos.info doc/gcc-amigaos.guide: gcc-amigaos.texi
++
++install-gcc-amigaos-doc: doc installdirs installdirs-guide \
++ $(DESTDIR)$(infodir)/gcc-amigaos.info \
++ $(DESTDIR)$(guidedir)/gcc-amigaos.guide
++### end-GG-local
++
++host-amigaos.o : $(srcdir)/config/m68k/host-amigaos.c $(CONFIG_H) $(SYSTEM_H) \
++ coretypes.h hosthooks.h hosthooks-def.h toplev.h diagnostic.h
++ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
++ $(srcdir)/config/m68k/host-amigaos.c
+diff --git a/gcc/config/m68k/xm-amigaos.h b/gcc/config/m68k/xm-amigaos.h
+new file mode 100755
+index 000000000000..bb571ba040b3
+--- /dev/null
++++ gcc/config/m68k/xm-amigaos.h
+@@ -0,0 +1,64 @@
++/* Configuration for GNU C-compiler for m68k Amiga, running AmigaOS.
++ Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2003
++ Free Software Foundation, Inc.
++ Contributed by Markus M. Wild (wild@amiga.physik.unizh.ch).
++
++This file is part of GCC.
++
++GCC 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.
++
++GCC 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 GCC; see the file COPYING. If not, write to
++the Free Software Foundation, 59 Temple Place - Suite 330,
++Boston, MA 02111-1307, USA. */
++
++#ifndef _FCNTL_H_
++#include <fcntl.h>
++#endif
++
++/* AmigaOS specific headers, such as from the Native Developer Update kits,
++ go in SYSTEM_INCLUDE_DIR. STANDARD_INCLUDE_DIR is the equivalent of
++ Unix "/usr/include". All other include paths are set in Makefile. */
++
++#define SYSTEM_INCLUDE_DIR "/gg/os-include"
++#define STANDARD_INCLUDE_DIR "/gg/include"
++
++#define STANDARD_EXEC_PREFIX_1 "/gg/libexec/gcc/"
++#define STANDARD_EXEC_PREFIX_2 "/gg/lib/gcc/"
++#define STANDARD_STARTFILE_PREFIX_1 "/gg/lib/"
++#define STANDARD_STARTFILE_PREFIX_2 "/gg/lib/"
++
++/* The AmigaOS stores file names with regard to upper/lower case, but actions
++ on existing files are case independent on the standard filesystems.
++
++ A good example of where this causes problems is the conflict between the C
++ include file <string.h> and the C++ include file <String.h>, where the C++
++ include file dir is searched first and thus causes includes of <string.h>
++ to include <String.h> instead.
++
++ In order to solve this problem we define the macro OPEN_CASE_SENSITIVE as
++ the name of the function that takes the same args as open() and does case
++ dependent opens. */
++
++#define OPEN_CASE_SENSITIVE(NAME, FLAGS, MODE) open ((NAME), (FLAGS) | O_CASE, (MODE))
++
++/* On the AmigaOS, there are two pathname separators, '/' (DIR_SEPARATOR)
++ and ':' (VOL_SEPARATOR). DIR_SEPARATOR defaults to the correct
++ character, so we don't have to explicitly set it. */
++
++#define DIR_SEPARATOR '/'
++#define VOL_SEPARATOR ':'
++#define DIR_SEPARATOR_2 VOL_SEPARATOR
++
++/* Zap PREFIX_INCLUDE_DIR, since with the AmigaOS port it is the same as
++ STANDARD_INCLUDE_DIR. */
++
++#undef PREFIX_INCLUDE_DIR
+diff --git a/gcc/expr.c b/gcc/expr.c
+index eb77ba0fe533..a2e6a7cac927 100644
+--- gcc/expr.c
++++ gcc/expr.c
+@@ -21,12 +21,12 @@ along with GCC; see the file COPYING3. If not see
+ #include "system.h"
+ #include "coretypes.h"
+ #include "backend.h"
++#include "tm_p.h"
+ #include "target.h"
+ #include "rtl.h"
+ #include "tree.h"
+ #include "gimple.h"
+ #include "predict.h"
+-#include "tm_p.h"
+ #include "ssa.h"
+ #include "expmed.h"
+ #include "optabs.h"
+diff --git a/gcc/function.c b/gcc/function.c
+index 401f8f90160d..0c35f094f4cb 100644
+--- gcc/function.c
++++ gcc/function.c
+@@ -35,13 +35,13 @@ along with GCC; see the file COPYING3. If not see
+ #include "system.h"
+ #include "coretypes.h"
+ #include "backend.h"
++#include "tm_p.h"
+ #include "target.h"
+ #include "rtl.h"
+ #include "tree.h"
+ #include "gimple-expr.h"
+ #include "cfghooks.h"
+ #include "df.h"
+-#include "tm_p.h"
+ #include "stringpool.h"
+ #include "expmed.h"
+ #include "optabs.h"
+diff --git a/gcc/ipa-chkp.c b/gcc/ipa-chkp.c
+index 86c48f14f64d..dc72a5f21021 100644
+--- gcc/ipa-chkp.c
++++ gcc/ipa-chkp.c
+@@ -23,6 +23,8 @@ along with GCC; see the file COPYING3. If not see
+ #include "system.h"
+ #include "coretypes.h"
+ #include "backend.h"
++#include "tm_p.h"
++#include "target.h"
+ #include "tree.h"
+ #include "gimple.h"
+ #include "tree-pass.h"
+diff --git a/gcc/tree-chkp.c b/gcc/tree-chkp.c
+index 4ca2d34607c6..472e203306b8 100644
+--- gcc/tree-chkp.c
++++ gcc/tree-chkp.c
+@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see
+ #include "system.h"
+ #include "coretypes.h"
+ #include "backend.h"
++#include "tm_p.h"
+ #include "target.h"
+ #include "rtl.h"
+ #include "tree.h"
+diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
+index 9f09d30b1f91..149c0c123804 100644
+--- gcc/var-tracking.c
++++ gcc/var-tracking.c
+@@ -89,13 +89,13 @@
+ #include "system.h"
+ #include "coretypes.h"
+ #include "backend.h"
++#include "tm_p.h"
+ #include "target.h"
+ #include "rtl.h"
+ #include "tree.h"
+ #include "cfghooks.h"
+ #include "alloc-pool.h"
+ #include "tree-pass.h"
+-#include "tm_p.h"
+ #include "insn-config.h"
+ #include "regs.h"
+ #include "emit-rtl.h"
+diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
+index bbbcd5d7ce0c..c8ce02987284 100755
+--- libstdc++-v3/configure
++++ libstdc++-v3/configure
+@@ -28820,6 +28820,10 @@ else
+
+ # Base decisions on target environment.
+ case "${host}" in
++ m68k-*-*)
++ # Nothing to do here.
++ ;;
++
+ arm*-*-symbianelf*)
+ # This is a freestanding configuration; there is nothing to do here.
+ ;;
+
+From 6951210c6e4901b5e963a19f5cae44bc0560a915 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 15 Dec 2016 00:37:25 +0100
+Subject: [PATCH 002/303] @N add .project file
+
+---
+ .project | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+ create mode 100644 .project
+
+diff --git a/.project b/.project
+new file mode 100644
+index 000000000000..ab5c4b198d08
+--- /dev/null
++++ .project
+@@ -0,0 +1,11 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<projectDescription>
++ <name>gcc-6</name>
++ <comment></comment>
++ <projects>
++ </projects>
++ <buildSpec>
++ </buildSpec>
++ <natures>
++ </natures>
++</projectDescription>
+
+From c81713312a097d40d212a5ac5bce13b1aff7b226 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 11 Jan 2017 12:09:34 +0100
+Subject: [PATCH 003/303] @B support named sections
+
+---
+ gcc/config/m68k/amigaos.c | 8 ++++++++
+ gcc/config/m68k/amigaos.h | 17 ++++++++++-------
+ 2 files changed, 18 insertions(+), 7 deletions(-)
+ mode change 100755 => 100644 gcc/config/m68k/amigaos.c
+ mode change 100755 => 100644 gcc/config/m68k/amigaos.h
+
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+old mode 100755
+new mode 100644
+index 90bc3218bab7..facb57a28aa3
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -771,3 +771,11 @@ amigaos_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno,
+ }
+
+
++/* Output assembly to switch to section NAME with attribute FLAGS. */
++
++extern void
++amiga_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_UNUSED)
++{
++ fprintf (asm_out_file, "\t.section\t%s\n", name);
++}
++
+diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h
+old mode 100755
+new mode 100644
+index 1a33225ab60f..d347a9be63db
+--- gcc/config/m68k/amigaos.h
++++ gcc/config/m68k/amigaos.h
+@@ -113,7 +113,15 @@ Boston, MA 02111-1307, USA. */
+ N_("Restore a4 in all functions") }, \
+ { "no-always-restore-a4", - MASK_ALWAYS_RESTORE_A4, \
+ N_("Do not restore a4 in all functions") }
+-
++
++
++/* Support sections in chip memory, currently '.datachip' only. */
++extern void
++amiga_named_section (const char *name, unsigned int flags, tree decl);
++
++#undef TARGET_ASM_NAMED_SECTION
++#define TARGET_ASM_NAMED_SECTION amiga_named_section
++
+ #if 0
+ /* Various ABI issues. */
+
+@@ -139,9 +147,6 @@ Boston, MA 02111-1307, USA. */
+ #undef PIC_OFFSET_TABLE_REGNUM
+ #define PIC_OFFSET_TABLE_REGNUM (flag_pic ? 12 : INVALID_REGNUM)
+
+-#undef PIC_REG
+-#define PIC_REG 12
+-
+ /* Use A5 as framepointer instead of A6, since the AmigaOS ABI requires A6
+ to be used as a shared library base pointer in direct library calls. */
+
+@@ -182,9 +187,7 @@ Boston, MA 02111-1307, USA. */
+
+ /* XXX: section support */
+ #if 0
+-/* Support sections in chip memory, currently '.datachip' only. */
+-#undef TARGET_ASM_NAMED_SECTION
+-#define TARGET_ASM_NAMED_SECTION amiga_named_section
++
+
+ /* We define TARGET_ASM_NAMED_SECTION, but we don't support arbitrary sections,
+ including '.gcc_except_table', so we emulate the standard behaviour. */
+
+From 6a04e2c9671b3d0d0de708cd0eb9fdb9bb4d5811 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 12 Jan 2017 00:10:47 +0100
+Subject: [PATCH 004/303] @B fix null ptr
+
+---
+ gcc/config/m68k/amigaos.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index facb57a28aa3..8727c7184812 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -508,7 +508,7 @@ _m68k_function_arg (CUMULATIVE_ARGS *cump, machine_mode mode, const_tree type)
+ /* FIXME: Two last conditions below are workarounds for bugs. */
+ else if (INTEGRAL_MODE_P (mode) && mode != CQImode && mode != CHImode)
+ {
+- if (POINTER_TYPE_P(type))
++ if (!type || POINTER_TYPE_P(type))
+ regbegin = 8; /* Ax */
+ else
+ regbegin = 0; /* Dx */
+
+From 09a2cda05b28a749e39d8e0af34ef3556eb21d6a Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 12 Jan 2017 00:12:11 +0100
+Subject: [PATCH 005/303] @I added quirky -fbaserel -fbaserel32 - really
+ working? nut sure...
+
+---
+ gcc/config/m68k/amigaos.h | 2 +-
+ gcc/config/m68k/amigaos.opt | 7 +++++++
+ gcc/config/m68k/m68k.c | 20 +++++++++++---------
+ 3 files changed, 19 insertions(+), 10 deletions(-)
+ mode change 100755 => 100644 gcc/config/m68k/amigaos.opt
+
+diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h
+index d347a9be63db..fd89bb34352c 100644
+--- gcc/config/m68k/amigaos.h
++++ gcc/config/m68k/amigaos.h
+@@ -471,7 +471,7 @@ extern tree amigaos_handle_type_attribute(tree *, tree, tree, int, bool*);
+ #define SUBTARGET_OVERRIDE_OPTIONS \
+ do \
+ { \
+- if (!TARGET_68020 && flag_pic==4) \
++ if (!TARGET_68020 && flag_pic==2) \
+ error ("-fbaserel32 is not supported on the 68000 or 68010\n"); \
+ if (amigaos_regparm > 0 && amigaos_regparm > AMIGAOS_MAX_REGPARM) \
+ error ("-mregparm=x with 1 <= x <= %d\n", AMIGAOS_MAX_REGPARM); \
+diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt
+old mode 100755
+new mode 100644
+index a9bc80c4f5b6..4298bc90abe1
+--- gcc/config/m68k/amigaos.opt
++++ gcc/config/m68k/amigaos.opt
+@@ -11,3 +11,10 @@ msmall-code
+ Target RejectNegative
+ small code model
+
++fbaserel
++Target Common Report Var(flag_pic,3) Negative(fpie) Init(-1)
++Backward compatibility, use -fpic now
++
++fbaserel32
++Target Common Report Var(flag_pic,4) Negative(fPIE) Init(-1)
++Backward compatibility, use -fPIC now
+\ No newline at end of file
+diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
+index fe3a939e1530..ce28681c1dc9 100644
+--- gcc/config/m68k/m68k.c
++++ gcc/config/m68k/m68k.c
+@@ -557,7 +557,7 @@ m68k_option_override (void)
+ : (m68k_cpu_flags & FL_COLDFIRE) != 0 ? FPUTYPE_COLDFIRE
+ : FPUTYPE_68881);
+
+- /* Sanity check to ensure that msep-data and mid-sahred-library are not
++ /* Sanity check to ensure that msep-data and mid-shared-library are not
+ * both specified together. Doing so simply doesn't make sense.
+ */
+ if (TARGET_SEP_DATA && TARGET_ID_SHARED_LIBRARY)
+@@ -568,7 +568,7 @@ m68k_option_override (void)
+ * -fpic but it hasn't been tested properly.
+ */
+ if (TARGET_SEP_DATA || TARGET_ID_SHARED_LIBRARY)
+- flag_pic = 2;
++ flag_pic = TARGET_68020 ? 2 : 1;
+
+ /* -mpcrel -fPIC uses 32-bit pc-relative displacements. Raise an
+ error if the target does not support them. */
+@@ -1139,9 +1139,9 @@ m68k_expand_prologue (void)
+ current_frame.reg_mask, true, true));
+ }
+
+- if (!TARGET_SEP_DATA
+- && crtl->uses_pic_offset_table)
+- emit_insn (gen_load_got (pic_offset_table_rtx));
++// if (!TARGET_SEP_DATA
++// && crtl->uses_pic_offset_table)
++// emit_insn (gen_load_got (pic_offset_table_rtx));
+ }
+
+ /* Return true if a simple (return) instruction is sufficient for this
+@@ -4693,8 +4693,10 @@ print_operand_address (FILE *file, rtx addr)
+ {
+ struct m68k_address address;
+
+- if (!m68k_decompose_address (QImode, addr, true, &address))
++ if (!m68k_decompose_address (QImode, addr, true, &address)) {
++ debug_rtx(addr);
+ gcc_unreachable ();
++ }
+
+ if (address.code == PRE_DEC)
+ fprintf (file, MOTOROLA ? "-(%s)" : "%s@-",
+@@ -4719,7 +4721,7 @@ print_operand_address (FILE *file, rtx addr)
+ /* (d16,PC) or (bd,PC,Xn) (with suppressed index register). */
+ fputc ('(', file);
+ output_addr_const (file, addr);
+- asm_fprintf (file, flag_pic == 1 ? ":w,%Rpc)" : ":l,%Rpc)");
++ asm_fprintf (file, flag_pic == 1 || flag_pic == 3 ? ":w,%Rpc)" : ":l,%Rpc)");
+ }
+ else
+ {
+@@ -5124,8 +5126,8 @@ m68k_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
+ /* Use the static chain register as a temporary (call-clobbered)
+ GOT pointer for this function. We can use the static chain
+ register because it isn't live on entry to the thunk. */
+- SET_REGNO (pic_offset_table_rtx, STATIC_CHAIN_REGNUM);
+- emit_insn (gen_load_got (pic_offset_table_rtx));
++// SET_REGNO (pic_offset_table_rtx, STATIC_CHAIN_REGNUM);
++// emit_insn (gen_load_got (pic_offset_table_rtx));
+ }
+ legitimize_pic_address (XEXP (mem, 0), Pmode, tmp);
+ mem = replace_equiv_address (mem, tmp);
+
+From e807bcc3fe2a83cc3b617c78c7f81685e861b5d1 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 12 Jan 2017 00:20:27 +0100
+Subject: [PATCH 006/303] @I
+
+---
+ gcc/config/m68k/amigaos.c | 0
+ gcc/config/m68k/amigaos.h | 0
+ gcc/config/m68k/amigaos.opt | 0
+ 3 files changed, 0 insertions(+), 0 deletions(-)
+ mode change 100644 => 100755 gcc/config/m68k/amigaos.c
+ mode change 100644 => 100755 gcc/config/m68k/amigaos.h
+ mode change 100644 => 100755 gcc/config/m68k/amigaos.opt
+
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+old mode 100644
+new mode 100755
+diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h
+old mode 100644
+new mode 100755
+diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt
+old mode 100644
+new mode 100755
+
+From 79e34a64428598cfb90bdf9f67aa32ad8c02effb Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 12 Jan 2017 00:21:21 +0100
+Subject: [PATCH 007/303] Revert "@I"
+
+This reverts commit e807bcc3fe2a83cc3b617c78c7f81685e861b5d1.
+---
+ gcc/config/m68k/amigaos.c | 0
+ gcc/config/m68k/amigaos.h | 0
+ gcc/config/m68k/amigaos.opt | 0
+ 3 files changed, 0 insertions(+), 0 deletions(-)
+ mode change 100755 => 100644 gcc/config/m68k/amigaos.c
+ mode change 100755 => 100644 gcc/config/m68k/amigaos.h
+ mode change 100755 => 100644 gcc/config/m68k/amigaos.opt
+
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+old mode 100755
+new mode 100644
+diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h
+old mode 100755
+new mode 100644
+diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt
+old mode 100755
+new mode 100644
+
+From 010fd69732e88d124686e46202f7a26bc9fa77ec Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 12 Jan 2017 15:13:10 +0100
+Subject: [PATCH 008/303] @B fix endless option parsing loop
+
+---
+ gcc/config/m68k/amigaos.opt | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt
+index 4298bc90abe1..f933fe29b98b 100644
+--- gcc/config/m68k/amigaos.opt
++++ gcc/config/m68k/amigaos.opt
+@@ -12,9 +12,9 @@ Target RejectNegative
+ small code model
+
+ fbaserel
+-Target Common Report Var(flag_pic,3) Negative(fpie) Init(-1)
++Target Common Report Var(flag_pic,3) Init(-1)
+ Backward compatibility, use -fpic now
+
+ fbaserel32
+-Target Common Report Var(flag_pic,4) Negative(fPIE) Init(-1)
++Target Common Report Var(flag_pic,4) Init(-1)
+ Backward compatibility, use -fPIC now
+\ No newline at end of file
+
+From c8b17fa2d8719ce6efc9535408966cd7ce87e2b8 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 31 Jan 2017 20:42:38 +0100
+Subject: [PATCH 009/303] @N re-added old target options, @R -fbaserel seems to
+ work
+
+---
+ gcc/config/m68k/amigaos.c | 7 +-
+ gcc/config/m68k/amigaos.opt | 20 ++-
+ gcc/config/m68k/m68k.c | 30 +++--
+ gcc/config/m68k/m68kamigaos.h | 283 ++++++++++++++++++++++++++++++++----------
+ 4 files changed, 257 insertions(+), 83 deletions(-)
+ mode change 100755 => 100644 gcc/config/m68k/m68kamigaos.h
+
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index 8727c7184812..19b0f5b4cc82 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -41,6 +41,8 @@ Boston, MA 02111-1307, USA. */
+ #include "config/m68k/amigaos.h"
+
+
++//int amiga_declare_object;
++
+ #if 0
+ static int amigaos_put_in_text (tree);
+ static rtx gen_stack_management_call (rtx, rtx, const char *);
+@@ -776,6 +778,9 @@ amigaos_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno,
+ extern void
+ amiga_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_UNUSED)
+ {
+- fprintf (asm_out_file, "\t.section\t%s\n", name);
++ if (0 == strncmp(".text", name, 5))
++ name = ".text";
++// fprintf (asm_out_file, "\t.section\t%s\n", name);
++ fprintf (asm_out_file, "\t%s\n", name);
+ }
+
+diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt
+index f933fe29b98b..29a3688470d0 100644
+--- gcc/config/m68k/amigaos.opt
++++ gcc/config/m68k/amigaos.opt
+@@ -12,9 +12,21 @@ Target RejectNegative
+ small code model
+
+ fbaserel
+-Target Common Report Var(flag_pic,3) Init(-1)
+-Backward compatibility, use -fpic now
++Target Common Report Var(flag_mybaserel,1)
++data is adressed relativ to a4
+
+ fbaserel32
+-Target Common Report Var(flag_pic,4) Init(-1)
+-Backward compatibility, use -fPIC now
+\ No newline at end of file
++Target Common Report Var(flag_mybaserel,2)
++data is adressed relativ to a4 with 32 bit offsets
++
++resident
++Target Common Report Var(flag_mybaserel,1)
++data is adressed relativ to a4, linked as resident
++
++resident32
++Target Common Report Var(flag_mybaserel,2)
++data is adressed relativ to a4 with 32 bit offsets, linked as resident
++
++mcrt=
++Target RejectNegative Var(amigaos_crt) Joined
++Specify startup binary
+\ No newline at end of file
+diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
+index ce28681c1dc9..387f0c1b9e02 100644
+--- gcc/config/m68k/m68k.c
++++ gcc/config/m68k/m68k.c
+@@ -1139,9 +1139,9 @@ m68k_expand_prologue (void)
+ current_frame.reg_mask, true, true));
+ }
+
+-// if (!TARGET_SEP_DATA
+-// && crtl->uses_pic_offset_table)
+-// emit_insn (gen_load_got (pic_offset_table_rtx));
++ if (!TARGET_SEP_DATA
++ && crtl->uses_pic_offset_table)
++ emit_insn (gen_load_got (pic_offset_table_rtx));
+ }
+
+ /* Return true if a simple (return) instruction is sufficient for this
+@@ -4496,7 +4496,10 @@ print_operand (FILE *file, rtx op, int letter)
+ && !(GET_CODE (XEXP (op, 0)) == CONST_INT
+ && INTVAL (XEXP (op, 0)) < 0x8000
+ && INTVAL (XEXP (op, 0)) >= -0x8000))
+- fprintf (file, MOTOROLA ? ".l" : ":l");
++#ifdef TARGET_AMIGA
++ if (!flag_mybaserel)
++#endif
++ fprintf (file, MOTOROLA ? ".l" : ":l");
+ }
+ else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode)
+ {
+@@ -4693,10 +4696,8 @@ print_operand_address (FILE *file, rtx addr)
+ {
+ struct m68k_address address;
+
+- if (!m68k_decompose_address (QImode, addr, true, &address)) {
+- debug_rtx(addr);
++ if (!m68k_decompose_address (QImode, addr, true, &address))
+ gcc_unreachable ();
+- }
+
+ if (address.code == PRE_DEC)
+ fprintf (file, MOTOROLA ? "-(%s)" : "%s@-",
+@@ -4721,7 +4722,7 @@ print_operand_address (FILE *file, rtx addr)
+ /* (d16,PC) or (bd,PC,Xn) (with suppressed index register). */
+ fputc ('(', file);
+ output_addr_const (file, addr);
+- asm_fprintf (file, flag_pic == 1 || flag_pic == 3 ? ":w,%Rpc)" : ":l,%Rpc)");
++ asm_fprintf (file, flag_pic == 1 ? ":w,%Rpc)" : ":l,%Rpc)");
+ }
+ else
+ {
+@@ -4738,6 +4739,15 @@ print_operand_address (FILE *file, rtx addr)
+ }
+ else
+ output_addr_const (file, addr);
++
++ if (!RTX_FLAG (addr, frame_related))
++ {
++// debug_rtx(addr);
++ if (flag_mybaserel == 1)
++ asm_fprintf (file, ".w(a4)");
++ else if (flag_mybaserel == 2)
++ asm_fprintf (file, "(a4)");
++ }
+ }
+ }
+ else
+@@ -5126,8 +5136,8 @@ m68k_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
+ /* Use the static chain register as a temporary (call-clobbered)
+ GOT pointer for this function. We can use the static chain
+ register because it isn't live on entry to the thunk. */
+-// SET_REGNO (pic_offset_table_rtx, STATIC_CHAIN_REGNUM);
+-// emit_insn (gen_load_got (pic_offset_table_rtx));
++ SET_REGNO (pic_offset_table_rtx, STATIC_CHAIN_REGNUM);
++ emit_insn (gen_load_got (pic_offset_table_rtx));
+ }
+ legitimize_pic_address (XEXP (mem, 0), Pmode, tmp);
+ mem = replace_equiv_address (mem, tmp);
+diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h
+old mode 100755
+new mode 100644
+index 0ce599138c7d..df0ce5b52ede
+--- gcc/config/m68k/m68kamigaos.h
++++ gcc/config/m68k/m68kamigaos.h
+@@ -25,6 +25,8 @@ along with GCC; see the file COPYING3. If not see
+ #define TARGET_AMIGA 1
+ #endif
+
++#define HAS_INIT_SECTION
++
+ #ifndef SWBEG_ASM_OP
+ #define SWBEG_ASM_OP "\t.swbeg\t"
+ #endif
+@@ -88,6 +90,28 @@ do { \
+ fprintf ((FILE), "%s%u\n", ALIGN_ASM_OP, 1 << (LOG)); \
+ } while (0)
+
++#if 0
++extern int amiga_declare_object;
++
++#define ASM_DECLARE_OBJECT_NAME(FILE,NAME,DECL) \
++if (!DECL_INITIAL (DECL) || \
++ initializer_zerop (DECL_INITIAL (decl))) \
++ { \
++ amiga_declare_object = 1; \
++ fprintf ((FILE), ".comm\t%s,", NAME); \
++ } \
++else \
++ASM_OUTPUT_LABEL (FILE, NAME)
++
++#undef ASM_OUTPUT_SKIP
++#define ASM_OUTPUT_SKIP(FILE,SIZE) \
++if (amiga_declare_object) \
++ fprintf (FILE, "%u\n", (int)(SIZE)); \
++else \
++ fprintf (FILE, "\t.skip %u\n", (int)(SIZE)); \
++amiga_declare_object = 0
++#endif
++
+ /* Register in which address to store a structure value is passed to a
+ function. The default in m68k.h is a1. For m68k/SVR4 it is a0. */
+
+@@ -145,14 +169,8 @@ do { \
+ fprintf ((FILE), "%s&%d\n", SWBEG_ASM_OP, XVECLEN (PATTERN (TABLE), 1));
+ /* end of stuff from m68kv4.h */
+
+-#undef ENDFILE_SPEC
+-#define ENDFILE_SPEC "crtend.o%s"
+-
+-#undef STARTFILE_SPEC
+-#define STARTFILE_SPEC "crtbegin.o%s"
+-
+ #ifndef BSS_SECTION_ASM_OP
+-#define BSS_SECTION_ASM_OP "\t.section\t.bss"
++#define BSS_SECTION_ASM_OP "\t.bss"
+ #endif
+
+ #ifndef ASM_OUTPUT_ALIGNED_BSS
+@@ -168,8 +186,6 @@ do { \
+ provided for compatibility reasons.
+ When creating shared libraries, use different 'errno'. */
+
+-
+-
+ #undef TARGET_OS_CPP_BUILTINS
+ #define TARGET_OS_CPP_BUILTINS() \
+ do \
+@@ -178,8 +194,8 @@ do { \
+ builtin_define ("__saveds=__attribute__((__saveds__))"); \
+ builtin_define ("__interrupt=__attribute__((__interrupt__))"); \
+ builtin_define ("__stackext=__attribute__((__stackext__))"); \
+- builtin_define ("__regargs_x=__attribute__((regparm))"); \
+- builtin_define ("__stdargs_x=__attribute__((stkparm))"); \
++ builtin_define ("__regargs=__attribute__((regparm))"); \
++ builtin_define ("__stdargs=__attribute__((stkparm))"); \
+ builtin_define ("__aligned=__attribute__((__aligned__(4)))"); \
+ builtin_define_std ("amiga"); \
+ builtin_define_std ("amigaos"); \
+@@ -195,6 +211,11 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+
+ #endif
+
++/* put return values in FPU build in FP0 Reg */
++#undef FUNCTION_VALUE_REGNO_P
++#define FUNCTION_VALUE_REGNO_P(N) \
++ ((N) == D0_REG || (N) == A0_REG || (TARGET_68881 && (N) == FP0_REG))
++
+ /* Inform the program which CPU we compile for. */
+
+ //#undef TARGET_CPU_CPP_BUILTINS
+@@ -229,14 +250,27 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ } \
+ while (0)
+ */
++
++/* When creating shared libraries, use different 'errno'. */
++#define CPP_IXEMUL_SPEC \
++ "%{!ansi:-Dixemul} -D__ixemul__ -D__ixemul " \
++ "%{malways-restore-a4:-Derrno=(*ixemul_errno)} " \
++ "%{mrestore-a4:-Derrno=(*ixemul_errno)}"
++#define CPP_LIBNIX_SPEC \
++ "-isystem %(sdk_root)libnix/include " \
++ "%{!ansi:-Dlibnix} -D__libnix__ -D__libnix"
++#define CPP_CLIB2_SPEC \
++ "-isystem %(sdk_root)clib2/include " \
++ "%{!ansi:-DCLIB2} -D__CLIB2__ -D__CLIB2"
++
+ /* Define __HAVE_68881__ in preprocessor according to the -m flags.
+ This will control the use of inline 68881 insns in certain macros.
+ Note: it should be set in TARGET_CPU_CPP_BUILTINS but TARGET_68881
+ isn't the same -m68881 since its also true for -m680[46]0 ...
+ Differentiate between libnix and ixemul. */
+
+-#define CPP_SPEC \
+- "%{m68881:-D__HAVE_68881__} " \
++#define CPP_SPEC \
++ "%{m68881:-D__HAVE_68881__} " \
+ "%{!ansi:" \
+ "%{m68020:-Dmc68020} " \
+ "%{mc68020:-Dmc68020} " \
+@@ -252,16 +286,10 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ "%{m68030:-D__mc68030__ -D__mc68030} " \
+ "%{m68040:-D__mc68040__ -D__mc68040} " \
+ "%{m68060:-D__mc68060__ -D__mc68060} " \
+- "%{noixemul:%{!ansi:%{!std=*:-Dlibnix}%{std=gnu*:-Dlibnix}} -D__libnix -D__libnix__} " \
+- "%{!noixemul:%{!ansi:%{!std=*:-Dixemul}%{std=gnu*:-Dixemul}} -D__ixemul -D__ixemul__}"
+-
+-/* Translate '-resident' to '-fbaserel' (they differ in linking stage only).
+- Don't put function addresses in registers for PC-relative code. */
+-
+-#define CC1_SPEC \
+- "%{resident:-fbaserel} " \
+- "%{resident32:-fbaserel32} " \
+- "%{msmall-code:-fno-function-cse}"
++ "%{noixemul:%(cpp_libnix)} " \
++ "%{mcrt=nix*:%(cpp_libnix)} " \
++ "%{mcrt=ixemul:%(cpp_ixemul)} " \
++ "%{mcrt=clib2:%(cpp_clib2)}"
+
+ /* Various -m flags require special flags to the assembler. */
+
+@@ -280,48 +308,56 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ #define ASM_CPU_DEFAULT_SPEC \
+ "%{!m680*:%{!mc680*:-m68040}}"
+
+-/* If debugging, tell the linker to output amiga-hunk symbols *and* a BSD
+- compatible debug hunk.
+- Also, pass appropriate linker flavours depending on user-supplied
+- commandline options. */
+-
+-#define LINK_SPEC \
+- "%{noixemul:-fl libnix} " \
+- "%{resident*:-amiga-datadata-reloc} " \
+- "%{resident|fbaserel:-m amiga_bss -fl libb} " \
+- "%{resident32|fbaserel32:-m amiga_bss -fl libb32} " \
+- "%{g:-amiga-debug-hunk} " \
+- "%(link_cpu)"
+-
+-#define LINK_CPU_SPEC \
+- "%{m6802*|mc68020|m68030|m68040|m68060:-fl libm020} " \
+- "%{m68881:-fl libm881}"
+-
+ /* Choose the right startup file, depending on whether we use base relative
+ code, base relative code with automatic relocation (-resident), their
+ 32-bit versions, libnix, profiling or plain crt0.o. */
+
+-#undef STARTFILE_SPEC
+-#define STARTFILE_SPEC \
+- "%{!noixemul:" \
+- "%{fbaserel:%{!resident:bcrt0.o%s}}" \
+- "%{resident:rcrt0.o%s}" \
+- "%{fbaserel32:%{!resident32:lcrt0.o%s}}" \
+- "%{resident32:scrt0.o%s}" \
+- "%{!resident:%{!fbaserel:%{!resident32:%{!fbaserel32:" \
+- "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}}}}}" \
+- "%{noixemul:" \
+- "%{resident:libnix/nrcrt0.o%s} " \
+- "%{!resident:%{fbaserel:libnix/nbcrt0.o%s}%{!fbaserel:libnix/ncrt0.o%s}}}"
++#define STARTFILE_IXEMUL_SPEC \
++ "%{fbaserel:%{!resident:bcrt0.o%s}}" \
++ "%{resident:rcrt0.o%s}" \
++ "%{fbaserel32:%{!resident32:lcrt0.o%s}}" \
++ "%{resident32:scrt0.o%s}" \
++ "%{!resident:%{!fbaserel:%{!resident32:%{!fbaserel32:" \
++ "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}}}}"
++#define STARTFILE_LIBNIX_SPEC \
++ "%(sdk_root)lib/libnix/" \
++ "%{ramiga-*:" \
++ "%{ramiga-lib:libinit.o%s}" \
++ "%{ramiga-libr:libinitr.o%s}" \
++ "%{ramiga-dev:devinit.o%s}}" \
++ "%{!ramiga-*:" \
++ "%{resident:nrcrt0.o%s}" \
++ "%{!resident:" \
++ "%{fbaserel:nbcrt0.o%s}" \
++ "%{!fbaserel:ncrt0.o%s}}}"
++#define STARTFILE_CLIB2_SPEC \
++ "%(sdk_root)clib2/lib/" \
++ "%{resident32:nr32crt0.o%s}" \
++ "%{!resident32:" \
++ "%{fbaserel32:nb32crt0.o%s}" \
++ "%{!fbaserel32:" \
++ "%{resident:nrcrt0.o%s}" \
++ "%{!resident:" \
++ "%{fbaserel:nbcrt0.o%s}" \
++ "%{!fbaserel:ncrt0.o%s}}}}"
+
+-#undef ENDFILE_SPEC
+-#define ENDFILE_SPEC \
+- "%{noixemul:-lstubs}"
++#undef STARTFILE_SPEC
++#define STARTFILE_SPEC \
++ "%{noixemul:%(startfile_libnix)} " \
++ "%{mcrt=nix*:%(startfile_libnix)} " \
++ "%{mcrt=ixemul:%(startfile_ixemul)} " \
++ "%{mcrt=clib2:%(startfile_clib2)}"
+
+-/* put return values in FPU build in FP0 Reg */
+-#undef FUNCTION_VALUE_REGNO_P
+-#define FUNCTION_VALUE_REGNO_P(N) \
+- ((N) == D0_REG || (N) == A0_REG || (TARGET_68881 && (N) == FP0_REG))
++#define ENDFILE_IXEMUL_SPEC ""
++#define ENDFILE_LIBNIX_SPEC "-lstubs"
++#define ENDFILE_CLIB2_SPEC ""
++
++#undef ENDFILE_SPEC
++#define ENDFILE_SPEC \
++ "%{noixemul:%(endfile_libnix)} " \
++ "%{mcrt=nix*:%(endfile_libnix)} " \
++ "%{mcrt=ixemul:%(endfile_ixemul)} " \
++ "%{mcrt=clib2:%(endfile_clib2)}"
+
+
+ /* Automatically search libamiga.a for AmigaOS specific functions. Note
+@@ -337,13 +373,106 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ to put in a -lamiga himself and get it in the wrong place, so that (for
+ example) calls like sprintf come from -lamiga rather than -lc. */
+
+-#undef LIB_SPEC
+-#define LIB_SPEC \
+- "%{!noixemul:" \
+- "%{p|pg:-lc_p}" \
+- "%{!p:%{!pg:-lc -lamiga -lc}}}" \
+- "%{noixemul:" \
+- "-lnixmain -lnix -lamiga %{mstackcheck|mstackextend:-lstack}}"
++#define LIB_IXEMUL_SPEC \
++ "%{!p:%{!pg:-lc -lamiga -lc}} " \
++ "%{p:-lc_p} %{pg:-lc_p}"
++#define LIB_LIBNIX_SPEC \
++ "-lnixmain -lnix -lstubs " \
++ "%{mcrt=*:-l%*} " \
++ "%{!mcrt=*:-lnix20} " \
++ "-lamiga " \
++ "%{mstackcheck:-lstack} " \
++ "%{mstackextend:-lstack}"
++#define LIB_CLIB2_SPEC \
++ "-lc -lamiga -ldebug " \
++ "%{mstackcheck:-lstack} " \
++ "%{mstackextend:-lstack}"
++
++#define LIB_SPEC \
++ "%{noixemul:%(lib_libnix)} " \
++ "%{mcrt=nix*:%(lib_libnix)} " \
++ "%{mcrt=ixemul:%(lib_ixemul)} " \
++ "%{mcrt=clib2:%(lib_clib2)}"
++
++#define LIBGCC_IXEMUL_SPEC ""
++#define LIBGCC_LIBNIX_SPEC "-lnix " \
++ "%{mcrt=*:-l%*} " \
++ "%{!mcrt=*:-lnix20}"
++#define LIBGCC_CLIB2_SPEC "-lc"
++//#define LIBGCC_SPEC "-lgcc "
++#define LIBGCC_SPEC " " \
++ "%{noixemul:%(libgcc_libnix)} " \
++ "%{mcrt=nix*:%(libgcc_libnix)} " \
++ "%{mcrt=ixemul:%(libgcc_ixemul)} " \
++ "%{mcrt=clib2:%(libgcc_clib2)}"
++
++/* If debugging, tell the linker to output amiga-hunk symbols *and* a BSD
++ compatible debug hunk.
++ Also, pass appropriate linker flavours depending on user-supplied
++ commandline options. */
++
++#define LINK_IXEMUL_SPEC ""
++#define LINK_LIBNIX_SPEC "-L%(sdk_root)libnix/lib -fl libnix"
++#define LINK_CLIB2_SPEC "-L%(sdk_root)clib2/lib"
++
++/* If debugging, tell the linker to output amiga-hunk symbols *and* a BSD
++ compatible debug hunk.
++ Also, pass appropriate linker flavours depending on user-supplied
++ commandline options. */
++
++#define LINK_SPEC \
++ "%{noixemul:%(link_libnix)} " \
++ "%{mcrt=nix*:%(link_libnix)} " \
++ "%{mcrt=ixemul:%(link_ixemul)} " \
++ "%{mcrt=clib2:%(link_clib2)} " \
++ "%{fbaserel:%{!resident:-m amiga_bss -fl libb}} " \
++ "%{resident:-m amiga_bss -amiga-datadata-reloc -fl libb} " \
++ "%{fbaserel32:%{!resident32:-m amiga_bss -fl libb32}} " \
++ "%{resident32:-m amiga_bss -amiga-datadata-reloc -fl libb32} " \
++ "%{g:-amiga-debug-hunk} " \
++ "%{m68020:-fl libm020} " \
++ "%{mc68020:-fl libm020} " \
++ "%{m68030:-fl libm020} " \
++ "%{m68040:-fl libm020} " \
++ "%{m68060:-fl libm020} " \
++ "%{m68020-40:-fl libm020} " \
++ "%{m68020-60:-fl libm020} " \
++ "%{m68881:-fl libm881}"
++
++/* Translate '-resident' to '-fbaserel' (they differ in linking stage only).
++ Don't put function addresses in registers for PC-relative code. */
++
++#define CC1_SPEC \
++ "%{resident:-fbaserel} " \
++ "%{resident32:-fbaserel32} " \
++ "%{msmall-code:-fno-function-cse}"
++
++#define LINK_CPU_SPEC \
++ "%{m6802*|mc68020|m68030|m68040|m68060:-fl libm020} " \
++ "%{m68881:-fl libm881}"
++
++/* [cahirwpz] A modified copy of LINK_COMMAND_SPEC from gcc/gcc.c file.
++ Don't prepend libgcc.a to link libraries and make sure the options is
++ at the end of command line. Otherwise linker chooses generic functions
++ from libgcc.a instead AmigaOS-specific counterparts from libnix.a. */
++
++#define LINK_COMMAND_SPEC \
++ "%{!fsyntax-only:" \
++ "%{!c:" \
++ "%{!M:" \
++ "%{!MM:" \
++ "%{!E:" \
++ "%{!S:" \
++ "%(linker) %l %X %{o*} %{A} %{d} %{e*} %{m} " \
++ "%{N} %{n} %{r} %{s} %{t} %{u*} %{x} %{z} %{Z} " \
++ "%{!A:%{!nostdlib:%{!nostartfiles:%S}}} " \
++ "%{static:} %{L*} %D %o " \
++ "%{!nostdlib:%{!nodefaultlibs:%L}} " \
++ "%{!A:%{!nostdlib:%{!nostartfiles:%E}}} " \
++ "%{!nostdlib:%{!nodefaultlibs:%G}} " \
++ "%{T*} }}}}}} " \
++
++
+
+ /* This macro defines names of additional specifications to put in the specs
+ that can be used in various specifications like CC1_SPEC. Its definition
+@@ -358,8 +487,26 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ #define EXTRA_SPECS \
+ { "asm_cpu", ASM_CPU_SPEC }, \
+ { "asm_cpu_default", ASM_CPU_DEFAULT_SPEC }, \
+- { "link_cpu", LINK_CPU_SPEC }
+-
++ { "link_cpu", LINK_CPU_SPEC }, \
++ {"sdk_root", TOOLDIR_BASE_PREFIX "m68k-amigaos/"}, \
++ {"cpp_ixemul", CPP_IXEMUL_SPEC}, \
++ {"cpp_libnix", CPP_LIBNIX_SPEC}, \
++ {"cpp_clib2", CPP_CLIB2_SPEC}, \
++ {"lib_ixemul", LIB_IXEMUL_SPEC}, \
++ {"lib_libnix", LIB_LIBNIX_SPEC}, \
++ {"lib_clib2", LIB_CLIB2_SPEC}, \
++ {"link_ixemul", LINK_IXEMUL_SPEC}, \
++ {"link_libnix", LINK_LIBNIX_SPEC}, \
++ {"link_clib2", LINK_CLIB2_SPEC}, \
++ {"startfile_ixemul", STARTFILE_IXEMUL_SPEC}, \
++ {"startfile_libnix", STARTFILE_LIBNIX_SPEC}, \
++ {"startfile_clib2", STARTFILE_CLIB2_SPEC}, \
++ {"endfile_ixemul", ENDFILE_IXEMUL_SPEC}, \
++ {"endfile_libnix", ENDFILE_LIBNIX_SPEC}, \
++ {"endfile_clib2", ENDFILE_CLIB2_SPEC}, \
++ {"libgcc_ixemul", LIBGCC_IXEMUL_SPEC}, \
++ {"libgcc_libnix", LIBGCC_LIBNIX_SPEC}, \
++ {"libgcc_clib2", LIBGCC_CLIB2_SPEC}
+
+ /* begin-GG-local: dynamic libraries */
+
+
+From d1df1ebb0f08f356222c21b1744476eb881b3b0c Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 1 Feb 2017 11:40:21 +0100
+Subject: [PATCH 010/303] @B mregparm was always enabled with 2 registers. Now
+ it's off.
+
+---
+ gcc/config/m68k/amigaos.c | 30 ++++++++++++++++++------------
+ gcc/config/m68k/amigaos.opt | 2 +-
+ gcc/config/m68k/m68k.c | 11 ++++++-----
+ 3 files changed, 25 insertions(+), 18 deletions(-)
+
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index 19b0f5b4cc82..e2dd5bab75f9 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -40,6 +40,12 @@ Boston, MA 02111-1307, USA. */
+ #include "diagnostic-core.h"
+ #include "config/m68k/amigaos.h"
+
++//#define MYDEBUG 1
++#ifdef MYDEBUG
++#define DPRINTF(x) printf x; fflush(stdout);
++#else
++#define DPRINTF(x)
++#endif
+
+ //int amiga_declare_object;
+
+@@ -379,8 +385,8 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype)
+ {
+ struct amigaos_args * cum = &mycum;
+ lastcum = cump;
+- cum->num_of_regs = amigaos_regparm;
+-// printf("amigaos_init_cumulative_args %p -> %d\r\n", cum, cum->num_of_regs); fflush(stdout);
++ cum->num_of_regs = amigaos_regparm > 0 ? amigaos_regparm : 0;
++ DPRINTF(("amigaos_init_cumulative_args %p -> %d\r\n", cum, cum->num_of_regs));
+
+ /* Initialize a variable CUM of type CUMULATIVE_ARGS
+ for a call to a function whose data type is FNTYPE.
+@@ -396,7 +402,7 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype)
+ else
+ {
+ tree ratree = lookup_attribute ("regparm", TYPE_ATTRIBUTES(fntype));
+- cum->num_of_regs = amigaos_regparm ?
++ cum->num_of_regs = amigaos_regparm != 0 ?
+ amigaos_regparm : AMIGAOS_DEFAULT_REGPARM;
+ if (ratree)
+ {
+@@ -456,7 +462,7 @@ amigaos_function_arg_advance (cumulative_args_t cum_v, machine_mode, const_tree,
+ CUMULATIVE_ARGS *cump = (CUMULATIVE_ARGS *) get_cumulative_args (cum_v);
+ /* Update the data in CUM to advance over an argument. */
+
+- // printf("amigaos_function_arg_advance1 %p\r\n", cump); fflush(stdout);
++ DPRINTF(("amigaos_function_arg_advance1 %p\r\n", cump));
+ if (cump != lastcum)
+ return;
+
+@@ -490,7 +496,7 @@ static struct rtx_def *
+ _m68k_function_arg (CUMULATIVE_ARGS *cump, machine_mode mode, const_tree type)
+ {
+ struct amigaos_args * cum = &mycum;
+- // printf("m68k_function_arg numOfRegs=%p\r\n", cum);
++ DPRINTF(("m68k_function_arg numOfRegs=%d\r\n", cum ? cum->num_of_regs : 0));
+
+ if (cump != lastcum)
+ return 0;
+@@ -550,7 +556,7 @@ _m68k_function_arg (CUMULATIVE_ARGS *cump, machine_mode mode, const_tree type)
+
+ if (cum->last_arg_reg != -1)
+ {
+- // printf("-> gen_rtx_REG %d\r\n", cum->last_arg_reg);
++ DPRINTF(("-> gen_rtx_REG %d\r\n", cum->last_arg_reg));
+ return gen_rtx_REG (mode, cum->last_arg_reg);
+ }
+ }
+@@ -566,7 +572,7 @@ amigaos_function_arg (cumulative_args_t cum_v, machine_mode mode,
+ {
+ struct amigaos_args * cum = &mycum;
+
+- // printf("amigaos_function_arg %p\r\n", cum_v.p); fflush(stdout);
++ DPRINTF(("amigaos_function_arg %p\r\n", cum_v.p));
+
+ CUMULATIVE_ARGS *cump = (CUMULATIVE_ARGS *) get_cumulative_args (cum_v);
+
+@@ -598,7 +604,7 @@ amigaos_function_arg (cumulative_args_t cum_v, machine_mode mode,
+ int
+ amigaos_comp_type_attributes (const_tree type1, const_tree type2)
+ {
+- printf("amigaos_comp_type_attributes\n");
++ DPRINTF(("amigaos_comp_type_attributes\n"));
+ /* Functions or methods are incompatible if they specify mutually exclusive
+ ways of passing arguments. */
+ if (TREE_CODE(type1) == FUNCTION_TYPE || TREE_CODE(type1) == METHOD_TYPE)
+@@ -688,7 +694,7 @@ amigaos_handle_type_attribute (tree *node, tree name, tree args,
+ {
+ tree nnn = *node;
+ do { // while (0);
+-// printf("%p with treecode %d\n", node, TREE_CODE(nnn)); fflush(stdout);
++ DPRINTF(("%p with treecode %d\n", node, TREE_CODE(nnn)));
+ if (TREE_CODE (nnn) == FUNCTION_DECL || TREE_CODE (nnn) == FUNCTION_TYPE
+ || TREE_CODE (nnn) == METHOD_TYPE)
+ {
+@@ -696,7 +702,7 @@ amigaos_handle_type_attribute (tree *node, tree name, tree args,
+ single class that should be used to pass arguments. */
+ if (is_attribute_p ("regparm", name))
+ {
+-// printf ("regparm found\n"); fflush(stdout);
++ DPRINTF(("regparm found\n"));
+
+ if (lookup_attribute ("stkparm", TYPE_ATTRIBUTES(nnn)))
+ {
+@@ -706,7 +712,7 @@ amigaos_handle_type_attribute (tree *node, tree name, tree args,
+ if (args && TREE_CODE (args) == TREE_LIST)
+ {
+ tree val = TREE_VALUE(args);
+-// printf ("regparm with val: %d\n", TREE_CODE(val));
++ DPRINTF(("regparm with val: %d\n", TREE_CODE(val)));
+ if (TREE_CODE (val) == INTEGER_CST)
+ {
+ int no = TREE_INT_CST_LOW(val);
+@@ -765,7 +771,7 @@ bool
+ amigaos_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno,
+ int *total, bool speed)
+ {
+-// printf("outer: %d, opno: %d", outer_code, opno); fflush(stdout);
++ DPRINTF(("outer: %d, opno: %d", outer_code, opno));
+ // debug_rtx(x);
+ bool r = m68k_rtx_costs (x, mode, outer_code, opno, total, speed);
+ *total *= 4;
+diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt
+index 29a3688470d0..212ab8e6efda 100644
+--- gcc/config/m68k/amigaos.opt
++++ gcc/config/m68k/amigaos.opt
+@@ -1,6 +1,6 @@
+
+ mregparm=
+-Target RejectNegative Var(amigaos_regparm) Joined UInteger
++Target RejectNegative Var(amigaos_regparm) Joined UInteger Init(-1)
+ Pass arguments through registers.
+
+ noixemul
+diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
+index 387f0c1b9e02..3ebc9020c4e0 100644
+--- gcc/config/m68k/m68k.c
++++ gcc/config/m68k/m68k.c
+@@ -166,7 +166,7 @@ static bool m68k_save_reg (unsigned int regno, bool interrupt_handler);
+ static bool m68k_ok_for_sibcall_p (tree, tree);
+ static bool m68k_tls_symbol_p (rtx);
+ static rtx m68k_legitimize_address (rtx, rtx, machine_mode);
+-#ifndef TARGET_AMIGAOS
++#ifndef TARGET_AMIGA
+ static
+ #endif
+ bool m68k_rtx_costs (rtx, machine_mode, int, int, int *, bool);
+@@ -2803,7 +2803,7 @@ const_int_cost (HOST_WIDE_INT i)
+ }
+ }
+
+-#ifndef TARGET_AMIGAOS
++#ifndef TARGET_AMIGA
+ static
+ #endif
+ bool
+@@ -4544,9 +4544,10 @@ m68k_get_reloc_decoration (enum m68k_reloc reloc)
+ switch (reloc)
+ {
+ case RELOC_GOT:
+- if (TARGET_AMIGAOS)
+- return "";
+- else if (MOTOROLA)
++// if (TARGET_AMIGA)
++// return "";
++// else
++ if (MOTOROLA)
+ {
+ if (flag_pic == 1 && TARGET_68020)
+ return "@GOT.w";
+
+From 0a6678c57629151eaec736ce82fa69dcc4e08c53 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 9 Feb 2017 22:01:27 +0100
+Subject: [PATCH 011/303] @B select correct crt0 file with baserel32
+
+---
+ gcc/config/m68k/m68kamigaos.h | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h
+index df0ce5b52ede..0650102861e8 100644
+--- gcc/config/m68k/m68kamigaos.h
++++ gcc/config/m68k/m68kamigaos.h
+@@ -329,7 +329,10 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ "%{resident:nrcrt0.o%s}" \
+ "%{!resident:" \
+ "%{fbaserel:nbcrt0.o%s}" \
+- "%{!fbaserel:ncrt0.o%s}}}"
++ "%{!fbaserel:" \
++ "%{fbaserel32:nlbcrt0.o%s}" \
++ "%{!fbaserel32:ncrt0.o%s}}}}"
++
+ #define STARTFILE_CLIB2_SPEC \
+ "%(sdk_root)clib2/lib/" \
+ "%{resident32:nr32crt0.o%s}" \
+@@ -430,6 +433,7 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ "%{fbaserel32:%{!resident32:-m amiga_bss -fl libb32}} " \
+ "%{resident32:-m amiga_bss -amiga-datadata-reloc -fl libb32} " \
+ "%{g:-amiga-debug-hunk} " \
++ "%{mcpu=68020:-fl libm020} " \
+ "%{m68020:-fl libm020} " \
+ "%{mc68020:-fl libm020} " \
+ "%{m68030:-fl libm020} " \
+
+From 38ec4180a5c5d9d7a87725d347838f3b55f837fa Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 9 Feb 2017 22:02:40 +0100
+Subject: [PATCH 012/303] @B -m68881 is not longer enabled by default for
+ -m68020
+
+---
+ gcc/config/m68k/m68k.c | 14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
+index 3ebc9020c4e0..c67194fa292d 100644
+--- gcc/config/m68k/m68k.c
++++ gcc/config/m68k/m68k.c
+@@ -352,11 +352,21 @@ struct gcc_target targetm = TARGET_INITIALIZER;
+ /* Base flags for 68k ISAs. */
+ #define FL_FOR_isa_00 FL_ISA_68000
+ #define FL_FOR_isa_10 (FL_FOR_isa_00 | FL_ISA_68010)
+-/* FL_68881 controls the default setting of -m68881. gcc has traditionally
++/* "FL_68881 controls the default setting of -m68881. gcc has traditionally
+ generated 68881 code for 68020 and 68030 targets unless explicitly told
+- not to. */
++ not to."
++
++ This is not true at least for the AMIGA.
++ gcc 2.93 does not set the 68881 flag.
++
++ */
++#ifdef TARGET_AMIGA
++#define FL_FOR_isa_20 (FL_FOR_isa_10 | FL_ISA_68020 \
++ | FL_BITFIELD | FL_CAS)
++#else
+ #define FL_FOR_isa_20 (FL_FOR_isa_10 | FL_ISA_68020 \
+ | FL_BITFIELD | FL_68881 | FL_CAS)
++#endif
+ #define FL_FOR_isa_40 (FL_FOR_isa_20 | FL_ISA_68040)
+ #define FL_FOR_isa_cpu32 (FL_FOR_isa_10 | FL_ISA_68020)
+
+
+From 5d9da9f9a2d9fec32fba2b7b9f2326d1f1c4f1f0 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 9 Feb 2017 22:05:42 +0100
+Subject: [PATCH 013/303] @R added a hack to support multiline __asm("...")
+ statements
+
+---
+ gcc/c/c-parser.c | 7 +++++++
+ libcpp/lex.c | 23 ++++++++++++++++++++++-
+ 2 files changed, 29 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
+index d8725b572b55..cde6fe0c1c59 100644
+--- gcc/c/c-parser.c
++++ gcc/c/c-parser.c
+@@ -3908,6 +3908,7 @@ c_parser_asm_string_literal (c_parser *parser)
+ static tree
+ c_parser_simple_asm_expr (c_parser *parser)
+ {
++ extern int in_assembler_directive;
+ tree str;
+ gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
+ /* ??? Follow the C++ parser rather than using the
+@@ -3919,7 +3920,13 @@ c_parser_simple_asm_expr (c_parser *parser)
+ parser->lex_untranslated_string = false;
+ return NULL_TREE;
+ }
++
++ // SBF: set in_assembler_directive to enable multi-line strings. And yes, it's a HACK.
++ in_assembler_directive = 1;
+ str = c_parser_asm_string_literal (parser);
++ // SBF: in_assembler_directive disabled
++ in_assembler_directive = 0;
++
+ parser->lex_untranslated_string = false;
+ if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+ {
+diff --git a/libcpp/lex.c b/libcpp/lex.c
+index e5a0397f3099..c2131adeb38e 100644
+--- libcpp/lex.c
++++ libcpp/lex.c
+@@ -64,6 +64,10 @@ static tokenrun *next_tokenrun (tokenrun *);
+
+ static _cpp_buff *new_buff (size_t);
+
++/*
++ * SBF: This flag is set if an asm statement is parsed, to support multiline strings in __asm()
++ */
++int in_assembler_directive;
+
+ /* Utility routine:
+
+@@ -1063,7 +1067,10 @@ _cpp_process_line_notes (cpp_reader *pfile, int in_comment)
+ else if (note->type == 0)
+ /* Already processed in lex_raw_string. */;
+ else
+- abort ();
++ {
++// abort ();
++ printf("ups: note type=%d\n", note->type);
++ }
+ }
+ }
+
+@@ -1875,6 +1882,20 @@ lex_string (cpp_reader *pfile, cpp_token *token, const uchar *base)
+ break;
+ else if (c == '\n')
+ {
++ /*
++ * SBF: allow multi-line strings
++ * Ignore the line end and move to next line.
++ * Only fail, if there is no next line
++ */
++ if (in_assembler_directive)
++ {
++ cpp_buffer *buffer = pfile->buffer;
++ if (buffer->cur < buffer->rlimit)
++ CPP_INCREMENT_LINE (pfile, 0);
++ buffer->need_line = true;
++ if (_cpp_get_fresh_line (pfile))
++ continue;
++ }
+ cur--;
+ /* Unmatched quotes always yield undefined behavior, but
+ greedy lexing means that what appears to be an unterminated
+
+From 6515b7470c3baf385a0dca132bc1c71acbcdda5f Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 12 Feb 2017 12:40:37 +0100
+Subject: [PATCH 014/303] @R allow used registers inside of the clobber list
+
+---
+ gcc/cfgexpand.c | 12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
+index b612293b1a7a..4215ae90c63d 100644
+--- gcc/cfgexpand.c
++++ gcc/cfgexpand.c
+@@ -2732,6 +2732,10 @@ tree_conflicts_with_clobbers_p (tree t, HARD_REG_SET *clobbered_regs)
+ {
+ /* Conflicts between asm-declared register variables and the clobber
+ list are not allowed. */
++ /*
++ * SBF: Why?
++ */
++#ifndef TARGET_AMIGA
+ tree overlap = tree_overlaps_hard_reg_set (t, clobbered_regs);
+
+ if (overlap)
+@@ -2744,7 +2748,7 @@ tree_conflicts_with_clobbers_p (tree t, HARD_REG_SET *clobbered_regs)
+ DECL_REGISTER (overlap) = 0;
+ return true;
+ }
+-
++#endif
+ return false;
+ }
+
+@@ -3255,11 +3259,15 @@ expand_asm_stmt (gasm *stmt)
+ if (reg_overlap_mentioned_p (clobbered_reg, output_rvec[k]))
+ internal_error ("asm clobber conflict with output operand");
+
++/**
++ * SBF: Why?
++ */
++#ifndef TARGET_AMIGA
+ for (unsigned k = 0; k < ninputs - ninout; ++k)
+ if (reg_overlap_mentioned_p (clobbered_reg, input_rvec[k]))
+ internal_error ("asm clobber conflict with input operand");
++#endif
+ }
+-
+ XVECEXP (body, 0, i++) = gen_rtx_CLOBBER (VOIDmode, clobbered_reg);
+ }
+
+
+From 7de2f3e6f2786a6d5e789230227f9d7c5f3e2316 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 12 Feb 2017 12:41:09 +0100
+Subject: [PATCH 015/303] @B fix mixing struct/class for the same class.
+
+---
+ gcc/coretypes.h | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/gcc/coretypes.h b/gcc/coretypes.h
+index 12067fdf5348..f0f069f6afa2 100644
+--- gcc/coretypes.h
++++ gcc/coretypes.h
+@@ -52,9 +52,9 @@ typedef const struct bitmap_head *const_bitmap;
+ struct simple_bitmap_def;
+ typedef struct simple_bitmap_def *sbitmap;
+ typedef const struct simple_bitmap_def *const_sbitmap;
+-struct rtx_def;
+-typedef struct rtx_def *rtx;
+-typedef const struct rtx_def *const_rtx;
++class rtx_def;
++typedef class rtx_def *rtx;
++typedef const class rtx_def *const_rtx;
+
+ /* Subclasses of rtx_def, using indentation to show the class
+ hierarchy, along with the relevant invariant.
+
+From bb99da7652edb584a7825632fdccf0db0d7080d4 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 12 Feb 2017 12:42:09 +0100
+Subject: [PATCH 016/303] @B fixed - on an unsigned value, add cast to signed
+
+---
+ gcc/hwint.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/hwint.h b/gcc/hwint.h
+index 14740ccc939a..cd4a35c98f7b 100644
+--- gcc/hwint.h
++++ gcc/hwint.h
+@@ -294,7 +294,7 @@ abs_hwi (HOST_WIDE_INT x)
+ inline unsigned HOST_WIDE_INT
+ absu_hwi (HOST_WIDE_INT x)
+ {
+- return x >= 0 ? (unsigned HOST_WIDE_INT)x : -(unsigned HOST_WIDE_INT)x;
++ return x >= 0 ? (unsigned HOST_WIDE_INT)x : -(signed HOST_WIDE_INT)x;
+ }
+
+ #endif /* ! GCC_HWINT_H */
+
+From e66d5a27e1e5257373172597fe9a699011b011d7 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 12 Feb 2017 12:42:45 +0100
+Subject: [PATCH 017/303] @N add amiga target
+
+---
+ libgcc/config.host | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/libgcc/config.host b/libgcc/config.host
+index 124f2ceaefda..1849a2ec1980 100644
+--- libgcc/config.host
++++ libgcc/config.host
+@@ -811,6 +811,9 @@ m32r-*-linux*)
+ m32rle-*-linux*)
+ tmake_file="$tmake_file m32r/t-linux t-fdpbit"
+ ;;
++m68k-*-amiga*)
++ tmake_file="$tmake_file m68k/t-floatlib"
++ ;;
+ m68k-*-elf* | fido-*-elf)
+ tmake_file="$tmake_file m68k/t-floatlib"
+ ;;
+
+From c61b7d29f7f89cbec99115f6dfbb81b5e2967188 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 12 Feb 2017 12:44:25 +0100
+Subject: [PATCH 018/303] @B fix specs and linking paths issues
+
+---
+ gcc/config/m68k/amigaos.h | 9 ++++-----
+ gcc/config/m68k/m68kamigaos.h | 41 ++++++++++++++++++++++-------------------
+ gcc/gcc.c | 37 +++++++++++++++++++++++++++++++++++++
+ 3 files changed, 63 insertions(+), 24 deletions(-)
+
+diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h
+index fd89bb34352c..5f3348feb726 100644
+--- gcc/config/m68k/amigaos.h
++++ gcc/config/m68k/amigaos.h
+@@ -122,7 +122,6 @@ amiga_named_section (const char *name, unsigned int flags, tree decl);
+ #undef TARGET_ASM_NAMED_SECTION
+ #define TARGET_ASM_NAMED_SECTION amiga_named_section
+
+-#if 0
+ /* Various ABI issues. */
+
+ /* This is (almost;-) BSD, so it wants DBX format. */
+@@ -183,12 +182,10 @@ amiga_named_section (const char *name, unsigned int flags, tree decl);
+ //#define DEFAULT_MAIN_RETURN c_expand_return (integer_zero_node)
+
+ #undef WCHAR_TYPE
+-#define WCHAR_TYPE "unsigned int"
++#define WCHAR_TYPE "unsigned short"
+
+ /* XXX: section support */
+-#if 0
+-
+-
++#if 0
+ /* We define TARGET_ASM_NAMED_SECTION, but we don't support arbitrary sections,
+ including '.gcc_except_table', so we emulate the standard behaviour. */
+ #undef TARGET_ASM_EXCEPTION_SECTION
+@@ -222,6 +219,8 @@ do \
+ } \
+ while (0)
+
++#if 0
++
+ /* Baserel support. */
+
+ /* Given that symbolic_operand(X), return TRUE if no special
+diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h
+index 0650102861e8..6ba2e6736b6a 100644
+--- gcc/config/m68k/m68kamigaos.h
++++ gcc/config/m68k/m68kamigaos.h
+@@ -257,10 +257,10 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ "%{malways-restore-a4:-Derrno=(*ixemul_errno)} " \
+ "%{mrestore-a4:-Derrno=(*ixemul_errno)}"
+ #define CPP_LIBNIX_SPEC \
+- "-isystem %(sdk_root)libnix/include " \
++ "-isystem %:sdk_root(libnix/include) " \
+ "%{!ansi:-Dlibnix} -D__libnix__ -D__libnix"
+ #define CPP_CLIB2_SPEC \
+- "-isystem %(sdk_root)clib2/include " \
++ "-isystem %:sdk_root(clib2/include) " \
+ "%{!ansi:-DCLIB2} -D__CLIB2__ -D__CLIB2"
+
+ /* Define __HAVE_68881__ in preprocessor according to the -m flags.
+@@ -320,7 +320,7 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ "%{!resident:%{!fbaserel:%{!resident32:%{!fbaserel32:" \
+ "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}}}}"
+ #define STARTFILE_LIBNIX_SPEC \
+- "%(sdk_root)lib/libnix/" \
++ "%:sdk_root(libnix/lib/libnix/ " \
+ "%{ramiga-*:" \
+ "%{ramiga-lib:libinit.o%s}" \
+ "%{ramiga-libr:libinitr.o%s}" \
+@@ -331,10 +331,11 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ "%{fbaserel:nbcrt0.o%s}" \
+ "%{!fbaserel:" \
+ "%{fbaserel32:nlbcrt0.o%s}" \
+- "%{!fbaserel32:ncrt0.o%s}}}}"
++ "%{!fbaserel32:ncrt0.o%s}}}}" \
++ ")"
+
+ #define STARTFILE_CLIB2_SPEC \
+- "%(sdk_root)clib2/lib/" \
++ "%:sdk_root(clib2/lib/ " \
+ "%{resident32:nr32crt0.o%s}" \
+ "%{!resident32:" \
+ "%{fbaserel32:nb32crt0.o%s}" \
+@@ -342,7 +343,8 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ "%{resident:nrcrt0.o%s}" \
+ "%{!resident:" \
+ "%{fbaserel:nbcrt0.o%s}" \
+- "%{!fbaserel:ncrt0.o%s}}}}"
++ "%{!fbaserel:ncrt0.o%s}}}}" \
++ ")"
+
+ #undef STARTFILE_SPEC
+ #define STARTFILE_SPEC \
+@@ -398,12 +400,11 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ "%{mcrt=clib2:%(lib_clib2)}"
+
+ #define LIBGCC_IXEMUL_SPEC ""
+-#define LIBGCC_LIBNIX_SPEC "-lnix " \
++#define LIBGCC_LIBNIX_SPEC "-lnix -fl libnix " \
+ "%{mcrt=*:-l%*} " \
+ "%{!mcrt=*:-lnix20}"
+ #define LIBGCC_CLIB2_SPEC "-lc"
+-//#define LIBGCC_SPEC "-lgcc "
+-#define LIBGCC_SPEC " " \
++#define LIBGCC_SPEC "-lgcc " \
+ "%{noixemul:%(libgcc_libnix)} " \
+ "%{mcrt=nix*:%(libgcc_libnix)} " \
+ "%{mcrt=ixemul:%(libgcc_ixemul)} " \
+@@ -415,8 +416,8 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ commandline options. */
+
+ #define LINK_IXEMUL_SPEC ""
+-#define LINK_LIBNIX_SPEC "-L%(sdk_root)libnix/lib -fl libnix"
+-#define LINK_CLIB2_SPEC "-L%(sdk_root)clib2/lib"
++#define LINK_LIBNIX_SPEC "-L%:sdk_root(libnix/lib) -fl libnix"
++#define LINK_CLIB2_SPEC "-L%:sdk_root(clib2/lib)"
+
+ /* If debugging, tell the linker to output amiga-hunk symbols *and* a BSD
+ compatible debug hunk.
+@@ -428,10 +429,10 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ "%{mcrt=nix*:%(link_libnix)} " \
+ "%{mcrt=ixemul:%(link_ixemul)} " \
+ "%{mcrt=clib2:%(link_clib2)} " \
+- "%{fbaserel:%{!resident:-m amiga_bss -fl libb}} " \
+- "%{resident:-m amiga_bss -amiga-datadata-reloc -fl libb} " \
+- "%{fbaserel32:%{!resident32:-m amiga_bss -fl libb32}} " \
+- "%{resident32:-m amiga_bss -amiga-datadata-reloc -fl libb32} " \
++ "%{fbaserel:%{!resident:-m amiga_bss -fl libb %{noixemul:-fl libnix} %{mcrt=nix*:-fl libnix}}} " \
++ "%{resident:-m amiga_bss -amiga-datadata-reloc -fl libb %{noixemul:-fl libnix} %{mcrt=nix*:-fl libnix}} " \
++ "%{fbaserel32:%{!resident32:-m amiga_bss -fl libb32 %{noixemul:-fl libnix} %{mcrt=nix*:-fl libnix}}} " \
++ "%{resident32:-m amiga_bss -amiga-datadata-reloc -fl libb32 %{noixemul:-fl libnix} %{mcrt=nix*:-fl libnix}} " \
+ "%{g:-amiga-debug-hunk} " \
+ "%{mcpu=68020:-fl libm020} " \
+ "%{m68020:-fl libm020} " \
+@@ -476,7 +477,10 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ "%{!nostdlib:%{!nodefaultlibs:%G}} " \
+ "%{T*} }}}}}} " \
+
++extern const char * amiga_m68k_prefix_func(int, const char **);
+
++#define EXTRA_SPEC_FUNCTIONS \
++ { "sdk_root", amiga_m68k_prefix_func },
+
+ /* This macro defines names of additional specifications to put in the specs
+ that can be used in various specifications like CC1_SPEC. Its definition
+@@ -489,10 +493,9 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ Do not define this macro if it does not need to do anything. */
+ #undef EXTRA_SPECS
+ #define EXTRA_SPECS \
+- { "asm_cpu", ASM_CPU_SPEC }, \
+- { "asm_cpu_default", ASM_CPU_DEFAULT_SPEC }, \
+- { "link_cpu", LINK_CPU_SPEC }, \
+- {"sdk_root", TOOLDIR_BASE_PREFIX "m68k-amigaos/"}, \
++ {"asm_cpu", ASM_CPU_SPEC }, \
++ {"asm_cpu_default", ASM_CPU_DEFAULT_SPEC }, \
++ {"link_cpu", LINK_CPU_SPEC }, \
+ {"cpp_ixemul", CPP_IXEMUL_SPEC}, \
+ {"cpp_libnix", CPP_LIBNIX_SPEC}, \
+ {"cpp_clib2", CPP_CLIB2_SPEC}, \
+diff --git a/gcc/gcc.c b/gcc/gcc.c
+index 0f042b0f12f7..479a912c7b3e 100644
+--- gcc/gcc.c
++++ gcc/gcc.c
+@@ -10075,3 +10075,40 @@ driver_get_configure_time_options (void (*cb) (const char *option,
+ obstack_free (&obstack, NULL);
+ n_switches = 0;
+ }
++
++#ifdef TARGET_AMIGA
++const char * amiga_m68k_prefix_func(int argc, const char ** argv) {
++ char * p = 0;
++ if (standard_libexec_prefix)
++ {
++ char * glp = concat(standard_libexec_prefix, "",0);
++ p = strrchr(glp, '/');
++ if (p)
++ {
++ *p = 0;
++ p = strrchr(glp, '/');
++ if (p)
++ {
++ *p = 0;
++ p = strrchr(glp, '/');
++ if (p)
++ {
++ p[1] = 0;
++ p = concat(glp, "m68k-amigaos/", 0);
++ }
++ }
++ }
++ free(glp);
++ }
++ if (!p)
++ p = concat("../../../../", "", 0);
++
++ for (int i = 0; i < argc; ++i) {
++ char * q = concat(p, argv[i], 0);
++ free(p);
++ p = q;
++ }
++// printf("amiga_m68k_prefix_func='%s'\n", p);
++ return p;
++}
++#endif
+
+From 476bb08c1155ea1a630fb456301fe273f24caca7 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 13 Feb 2017 18:47:13 +0100
+Subject: [PATCH 019/303] @B disable builtins which also disables
+ tree-loop-distribute-patterns which causes an infinite recursion since e.g.
+ in memset the pattern is recognized and memset is called...
+
+---
+ gcc/config/m68k/m68kamigaos.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h
+index 6ba2e6736b6a..a0ab3f1a91da 100644
+--- gcc/config/m68k/m68kamigaos.h
++++ gcc/config/m68k/m68kamigaos.h
+@@ -576,3 +576,5 @@ amigaos_prelink_hook((const char **)(LD1_ARGV), (STRIP))
+ #undef FIXED_INCLUDE_DIR
+ #define FIXED_INCLUDE_DIR CROSS_INCLUDE_DIR "/../../os-include"
+
++// this disables tree_loop_distribute_patterns
++#define C_COMMON_OVERRIDE_OPTIONS flag_no_builtin = 1
+
+From c1d1a53baaa94d5560d8e5d9daa749fb8b773b3a Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 16 Feb 2017 12:20:05 +0100
+Subject: [PATCH 020/303] @B fix includes for target AMIGA
+
+---
+ libstdc++-v3/include/c_global/cstdio | 2 ++
+ libstdc++-v3/include/tr1/cstdint | 1 +
+ 2 files changed, 3 insertions(+)
+
+diff --git a/libstdc++-v3/include/c_global/cstdio b/libstdc++-v3/include/c_global/cstdio
+index 86d524f96a62..522d065d4dc6 100644
+--- libstdc++-v3/include/c_global/cstdio
++++ libstdc++-v3/include/c_global/cstdio
+@@ -149,7 +149,9 @@ namespace std
+ #if _GLIBCXX_USE_C99_STDIO
+
+ #undef snprintf
++#ifndef AMIGA
+ #undef vfscanf
++#endif
+ #undef vscanf
+ #undef vsnprintf
+ #undef vsscanf
+diff --git a/libstdc++-v3/include/tr1/cstdint b/libstdc++-v3/include/tr1/cstdint
+index 7304d9008413..cdb8b704f0bb 100644
+--- libstdc++-v3/include/tr1/cstdint
++++ libstdc++-v3/include/tr1/cstdint
+@@ -31,6 +31,7 @@
+
+ #pragma GCC system_header
+
++#include <stdint.h>
+ #include <bits/c++config.h>
+
+ // For 8.22.1/1 (see C99, Notes 219, 220, 222)
+
+From 8a098e5a7bb1c14c1afa7946dce4416596418e8a Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 16 Feb 2017 13:48:01 +0100
+Subject: [PATCH 021/303] @B fix header only for AMIGA
+
+---
+ libstdc++-v3/include/tr1/cstdint | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/libstdc++-v3/include/tr1/cstdint b/libstdc++-v3/include/tr1/cstdint
+index cdb8b704f0bb..7d6ab77ce17a 100644
+--- libstdc++-v3/include/tr1/cstdint
++++ libstdc++-v3/include/tr1/cstdint
+@@ -30,8 +30,9 @@
+ #define _GLIBCXX_TR1_CSTDINT 1
+
+ #pragma GCC system_header
+-
++#ifdef AMIGA
+ #include <stdint.h>
++#endif
+ #include <bits/c++config.h>
+
+ // For 8.22.1/1 (see C99, Notes 219, 220, 222)
+
+From a3e959953b7386e1576961fb4666f704b2edac7f Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sat, 18 Feb 2017 20:19:06 +0100
+Subject: [PATCH 022/303] @V version resports now 6.3.1a instead of 6.3.1
+
+---
+ gcc/BASE-VER | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/BASE-VER b/gcc/BASE-VER
+index dc0208aba8e4..b557a4031409 100644
+--- gcc/BASE-VER
++++ gcc/BASE-VER
+@@ -1 +1 @@
+-6.3.1
++6.3.1a
+
+From 708b7bc6002cf54e04d7f67e3fdb6627aead7714 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 19 Feb 2017 20:24:20 +0100
+Subject: [PATCH 023/303] @B fix __regargs, __stdargs plus register
+ distribution
+
+---
+ gcc/config/m68k/amigaos-protos.h | 4 ++--
+ gcc/config/m68k/amigaos.c | 19 +++++++++++--------
+ gcc/config/m68k/amigaos.h | 2 ++
+ gcc/config/m68k/m68kamigaos.h | 4 ++--
+ 4 files changed, 17 insertions(+), 12 deletions(-)
+ mode change 100755 => 100644 gcc/config/m68k/amigaos-protos.h
+
+diff --git a/gcc/config/m68k/amigaos-protos.h b/gcc/config/m68k/amigaos-protos.h
+old mode 100755
+new mode 100644
+index 66b553ab568f..97733002f4f9
+--- gcc/config/m68k/amigaos-protos.h
++++ gcc/config/m68k/amigaos-protos.h
+@@ -24,7 +24,7 @@ Boston, MA 02111-1307, USA. */
+ #undef TARGET_AMIGAOS
+ #define TARGET_AMIGAOS 1
+
+-extern void amigaos_init_cumulative_args (CUMULATIVE_ARGS *, tree);
++extern void amigaos_init_cumulative_args (CUMULATIVE_ARGS *, tree, tree);
+
+ /* Initialize a variable CUM of type CUMULATIVE_ARGS
+ for a call to a function whose data type is FNTYPE.
+@@ -32,7 +32,7 @@ extern void amigaos_init_cumulative_args (CUMULATIVE_ARGS *, tree);
+
+ #undef INIT_CUMULATIVE_ARGS
+ #define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
+- (amigaos_init_cumulative_args(&(CUM), (FNTYPE)))
++ (amigaos_init_cumulative_args(&(CUM), (FNTYPE), (INDIRECT)))
+
+
+ extern int amigaos_restore_a4 (void);
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index e2dd5bab75f9..ad4bb9130cd5 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -381,7 +381,7 @@ static CUMULATIVE_ARGS * lastcum;
+ For a library call, FNTYPE is 0. */
+
+ void
+-amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype)
++amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl)
+ {
+ struct amigaos_args * cum = &mycum;
+ lastcum = cump;
+@@ -397,11 +397,12 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype)
+
+ if (fntype)
+ {
+- if (lookup_attribute ("stkparm", TYPE_ATTRIBUTES(fntype)))
+- cum->num_of_regs = 0;
++ tree attrs = DECL_ATTRIBUTES(decl);
++ if (lookup_attribute ("stkparm", attrs))
++ cum->num_of_regs = 0;
+ else
+ {
+- tree ratree = lookup_attribute ("regparm", TYPE_ATTRIBUTES(fntype));
++ tree ratree = lookup_attribute ("regparm", attrs);
+ cum->num_of_regs = amigaos_regparm != 0 ?
+ amigaos_regparm : AMIGAOS_DEFAULT_REGPARM;
+ if (ratree)
+@@ -530,11 +531,11 @@ _m68k_function_arg (CUMULATIVE_ARGS *cump, machine_mode mode, const_tree type)
+ long mask;
+
+ look_for_reg: mask = 1 << regbegin;
+- for (reg = 0; reg < cum->num_of_regs; reg++, mask <<= 1)
++ for (reg = 0; reg < AMIGAOS_MAX_REGPARM; reg++, mask <<= 1)
+ if (!(cum->regs_already_used & mask))
+ {
+ int end;
+- for (end = reg; end < cum->num_of_regs && end < reg + len;
++ for (end = reg; end < AMIGAOS_MAX_REGPARM && end < reg + len;
+ end++, mask <<= 1)
+ if (cum->regs_already_used & mask)
+ break;
+@@ -546,8 +547,9 @@ _m68k_function_arg (CUMULATIVE_ARGS *cump, machine_mode mode, const_tree type)
+ }
+ }
+
+- if (reg == cum->num_of_regs && altregbegin != -1)
++ if (reg == AMIGAOS_MAX_REGPARM && altregbegin != -1)
+ {
++ DPRINTF(("look for alt reg\n"));
+ regbegin = altregbegin;
+ altregbegin = -1;
+ goto look_for_reg;
+@@ -556,6 +558,7 @@ _m68k_function_arg (CUMULATIVE_ARGS *cump, machine_mode mode, const_tree type)
+
+ if (cum->last_arg_reg != -1)
+ {
++ --cum->num_of_regs;
+ DPRINTF(("-> gen_rtx_REG %d\r\n", cum->last_arg_reg));
+ return gen_rtx_REG (mode, cum->last_arg_reg);
+ }
+@@ -771,7 +774,7 @@ bool
+ amigaos_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno,
+ int *total, bool speed)
+ {
+- DPRINTF(("outer: %d, opno: %d", outer_code, opno));
++// DPRINTF(("outer: %d, opno: %d", outer_code, opno));
+ // debug_rtx(x);
+ bool r = m68k_rtx_costs (x, mode, outer_code, opno, total, speed);
+ *total *= 4;
+diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h
+index 5f3348feb726..71a978e6df97 100644
+--- gcc/config/m68k/amigaos.h
++++ gcc/config/m68k/amigaos.h
+@@ -481,6 +481,8 @@ while (0)
+ affects_type_identity } */
+ #define SUBTARGET_ATTRIBUTES \
+ { "regparm", 1, 1, true, false, false, amigaos_handle_type_attribute,\
++ false }, \
++ { "stkparm", 0, 0, true, false, false, amigaos_handle_type_attribute,\
+ false },
+
+ #define GOT_SYMBOL_NAME ""
+diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h
+index a0ab3f1a91da..539d5f0bf934 100644
+--- gcc/config/m68k/m68kamigaos.h
++++ gcc/config/m68k/m68kamigaos.h
+@@ -194,8 +194,8 @@ amiga_declare_object = 0
+ builtin_define ("__saveds=__attribute__((__saveds__))"); \
+ builtin_define ("__interrupt=__attribute__((__interrupt__))"); \
+ builtin_define ("__stackext=__attribute__((__stackext__))"); \
+- builtin_define ("__regargs=__attribute__((regparm))"); \
+- builtin_define ("__stdargs=__attribute__((stkparm))"); \
++ builtin_define ("__regargs=__attribute__((__regparm__))"); \
++ builtin_define ("__stdargs=__attribute__((__stkparm__))"); \
+ builtin_define ("__aligned=__attribute__((__aligned__(4)))"); \
+ builtin_define_std ("amiga"); \
+ builtin_define_std ("amigaos"); \
+
+From e9ccb451229b09a1fdb64eb125d3ac0c733c5e9e Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 20 Feb 2017 08:32:06 +0100
+Subject: [PATCH 024/303] @B do not append (a4) to function references.
+
+---
+ gcc/config/m68k/m68k.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
+index c67194fa292d..bd76c766a735 100644
+--- gcc/config/m68k/m68k.c
++++ gcc/config/m68k/m68k.c
+@@ -4751,7 +4751,7 @@ print_operand_address (FILE *file, rtx addr)
+ else
+ output_addr_const (file, addr);
+
+- if (!RTX_FLAG (addr, frame_related))
++ if (!RTX_FLAG (addr, frame_related) && !SYMBOL_REF_FUNCTION_P(addr))
+ {
+ // debug_rtx(addr);
+ if (flag_mybaserel == 1)
+
+From 40f1afb4c03c2bb79e86c5fb8fa2e7daa45d8600 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 20 Feb 2017 08:35:34 +0100
+Subject: [PATCH 025/303] @B enable reg-rename in O2+ and fix it.
+
+---
+ gcc/regrename.c | 5 +++--
+ gcc/toplev.c | 2 +-
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/gcc/regrename.c b/gcc/regrename.c
+index 9643f328ea3e..9816d3eaf5d2 100644
+--- gcc/regrename.c
++++ gcc/regrename.c
+@@ -406,8 +406,9 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class,
+
+ /* In the first pass, we force the renaming of registers that
+ don't belong to PREFERRED_CLASS to registers that do, even
+- though the latters were used not very long ago. */
+- if ((pass == 0
++ though the latters were used not very long ago.
++ Also use a register if no best_new_reg was found till now */
++ if (((pass == 0 || !has_preferred_class)
+ && !TEST_HARD_REG_BIT (reg_class_contents[preferred_class],
+ best_new_reg))
+ || tick[best_new_reg] > tick[new_reg])
+diff --git a/gcc/toplev.c b/gcc/toplev.c
+index 8979d2634260..96d17ee1cccc 100644
+--- gcc/toplev.c
++++ gcc/toplev.c
+@@ -1299,7 +1299,7 @@ process_options (void)
+ flag_web = flag_unroll_loops || flag_peel_loops;
+
+ if (flag_rename_registers == AUTODETECT_VALUE)
+- flag_rename_registers = flag_unroll_loops || flag_peel_loops;
++ flag_rename_registers = flag_unroll_loops || flag_peel_loops || optimize >= 2;
+
+ if (flag_non_call_exceptions)
+ flag_asynchronous_unwind_tables = 1;
+
+From b980bd29d8cf05a2c6d6c947547b3f1e1c4cff23 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 20 Feb 2017 10:52:45 +0100
+Subject: [PATCH 026/303] @B fix npe in amigaos_init_cumulative_args
+
+---
+ gcc/config/m68k/amigaos.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index ad4bb9130cd5..c675bc8e01ed 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -395,7 +395,7 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl)
+ cum->last_arg_reg = -1;
+ cum->regs_already_used = 0;
+
+- if (fntype)
++ if (decl)
+ {
+ tree attrs = DECL_ATTRIBUTES(decl);
+ if (lookup_attribute ("stkparm", attrs))
+
+From 215f15335dca293e65f47fde15a3d6486c551629 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 23 Feb 2017 12:46:18 +0100
+Subject: [PATCH 027/303] @B -mregparm conforms now to the spec.
+
+---
+ gcc/config/m68k/amigaos.c | 22 +++++++++++-----------
+ 1 file changed, 11 insertions(+), 11 deletions(-)
+
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index c675bc8e01ed..916140bdc628 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -386,7 +386,7 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl)
+ struct amigaos_args * cum = &mycum;
+ lastcum = cump;
+ cum->num_of_regs = amigaos_regparm > 0 ? amigaos_regparm : 0;
+- DPRINTF(("amigaos_init_cumulative_args %p -> %d\r\n", cum, cum->num_of_regs));
++ DPRINTF(("0amigaos_init_cumulative_args %p -> %d\r\n", cum, cum->num_of_regs));
+
+ /* Initialize a variable CUM of type CUMULATIVE_ARGS
+ for a call to a function whose data type is FNTYPE.
+@@ -451,6 +451,7 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl)
+ else
+ /* Call to compiler-support function. */
+ cum->formal_type = 0;
++ DPRINTF(("1amigaos_init_cumulative_args %p -> %d\r\n", cum, cum->num_of_regs));
+ }
+
+ /* Update the data in CUM to advance over an argument. */
+@@ -531,11 +532,11 @@ _m68k_function_arg (CUMULATIVE_ARGS *cump, machine_mode mode, const_tree type)
+ long mask;
+
+ look_for_reg: mask = 1 << regbegin;
+- for (reg = 0; reg < AMIGAOS_MAX_REGPARM; reg++, mask <<= 1)
++ for (reg = 0; reg < cum->num_of_regs; reg++, mask <<= 1)
+ if (!(cum->regs_already_used & mask))
+ {
+ int end;
+- for (end = reg; end < AMIGAOS_MAX_REGPARM && end < reg + len;
++ for (end = reg; end < cum->num_of_regs && end < reg + len;
+ end++, mask <<= 1)
+ if (cum->regs_already_used & mask)
+ break;
+@@ -547,18 +548,17 @@ _m68k_function_arg (CUMULATIVE_ARGS *cump, machine_mode mode, const_tree type)
+ }
+ }
+
+- if (reg == AMIGAOS_MAX_REGPARM && altregbegin != -1)
+- {
+- DPRINTF(("look for alt reg\n"));
+- regbegin = altregbegin;
+- altregbegin = -1;
+- goto look_for_reg;
+- }
++// if (reg == AMIGAOS_MAX_REGPARM && altregbegin != -1)
++// {
++// DPRINTF(("look for alt reg\n"));
++// regbegin = altregbegin;
++// altregbegin = -1;
++// goto look_for_reg;
++// }
+ }
+
+ if (cum->last_arg_reg != -1)
+ {
+- --cum->num_of_regs;
+ DPRINTF(("-> gen_rtx_REG %d\r\n", cum->last_arg_reg));
+ return gen_rtx_REG (mode, cum->last_arg_reg);
+ }
+
+From 419b54e138b5322b468189fbf9e234f6315b0914 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 23 Feb 2017 12:47:40 +0100
+Subject: [PATCH 028/303] @B if -fbaserel32 -m68020 (or better) must be present
+ too
+
+---
+ gcc/config/m68k/amigaos.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h
+index 71a978e6df97..afc2c6563143 100644
+--- gcc/config/m68k/amigaos.h
++++ gcc/config/m68k/amigaos.h
+@@ -470,7 +470,7 @@ extern tree amigaos_handle_type_attribute(tree *, tree, tree, int, bool*);
+ #define SUBTARGET_OVERRIDE_OPTIONS \
+ do \
+ { \
+- if (!TARGET_68020 && flag_pic==2) \
++ if (!TARGET_68020 && flag_mybaserel==2) \
+ error ("-fbaserel32 is not supported on the 68000 or 68010\n"); \
+ if (amigaos_regparm > 0 && amigaos_regparm > AMIGAOS_MAX_REGPARM) \
+ error ("-mregparm=x with 1 <= x <= %d\n", AMIGAOS_MAX_REGPARM); \
+
+From f76ce97a5f8b9542814e5700e9d728ede215749d Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 23 Feb 2017 12:48:23 +0100
+Subject: [PATCH 029/303] @I -msmall-code sets now flag_smallcode
+
+---
+ gcc/config/m68k/amigaos.opt | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt
+index 212ab8e6efda..1faa3f2eeb26 100644
+--- gcc/config/m68k/amigaos.opt
++++ gcc/config/m68k/amigaos.opt
+@@ -8,7 +8,7 @@ Target RejectNegative
+ Do not use ixemul.library - use libnix instead to link
+
+ msmall-code
+-Target RejectNegative
++Target RejectNegative Var(flag_smallcode,1)
+ small code model
+
+ fbaserel
+
+From d08bd9d2a479285104f394f70be45e5f77dfa419 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 23 Feb 2017 12:50:51 +0100
+Subject: [PATCH 030/303] @B fix baserel(32): use a4 only if common or bss is
+ referenced @N support -msmall-code
+
+---
+ gcc/config/m68k/m68k.c | 36 ++++++++++++++++++++++++++++++------
+ 1 file changed, 30 insertions(+), 6 deletions(-)
+
+diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
+index bd76c766a735..b6ef99024ea6 100644
+--- gcc/config/m68k/m68k.c
++++ gcc/config/m68k/m68k.c
+@@ -4751,14 +4751,38 @@ print_operand_address (FILE *file, rtx addr)
+ else
+ output_addr_const (file, addr);
+
+- if (!RTX_FLAG (addr, frame_related) && !SYMBOL_REF_FUNCTION_P(addr))
++#ifdef TARGET_AMIGA
++ if (SYMBOL_REF_FUNCTION_P(addr))
+ {
+-// debug_rtx(addr);
+- if (flag_mybaserel == 1)
+- asm_fprintf (file, ".w(a4)");
+- else if (flag_mybaserel == 2)
+- asm_fprintf (file, "(a4)");
++ if (flag_smallcode)
++ asm_fprintf(file, ":w(pc)");
+ }
++ else if (flag_mybaserel)
++ {
++ /* search the decl. */
++ tree decl = SYMBOL_REF_DECL (addr);
++ if (!decl)
++ {
++ rtx x = XEXP(addr, 0);
++ if (CONSTANT_POOL_ADDRESS_P(x))
++ decl = SYMBOL_REF_DECL (x);
++ if (!decl)
++ {
++ x = XEXP(x, 0);
++ decl = SYMBOL_REF_DECL (x);
++ }
++ }
++
++ /* Qualifies for a4 if common or bss. Do not ref to .text! */
++ if (decl && (DECL_COMMON (decl) || bss_initializer_p (decl)))
++ {
++ if (flag_mybaserel == 1)
++ asm_fprintf (file, ":W(a4)");
++ else if (flag_mybaserel == 2)
++ asm_fprintf (file, ":L(a4)");
++ }
++ }
++#endif
+ }
+ }
+ else
+
+From c72e9ebfc07a0b31d523b9d7428544427fe551b7 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 23 Feb 2017 20:15:17 +0100
+Subject: [PATCH 031/303] @B undo a too optimistic change ;)
+
+---
+ gcc/regrename.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/regrename.c b/gcc/regrename.c
+index 9816d3eaf5d2..df4c320700c5 100644
+--- gcc/regrename.c
++++ gcc/regrename.c
+@@ -408,7 +408,7 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class,
+ don't belong to PREFERRED_CLASS to registers that do, even
+ though the latters were used not very long ago.
+ Also use a register if no best_new_reg was found till now */
+- if (((pass == 0 || !has_preferred_class)
++ if (((pass == 0)
+ && !TEST_HARD_REG_BIT (reg_class_contents[preferred_class],
+ best_new_reg))
+ || tick[best_new_reg] > tick[new_reg])
+
+From 181421087bf57fab0f047c47861b5c2a1e745d96 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 14 Mar 2017 21:38:30 +0100
+Subject: [PATCH 032/303] @R add better -fbaserel(32) support for TARGET_AMIGA
+
+---
+ gcc/BASE-VER | 2 +-
+ gcc/config/m68k/amigaos.c | 51 +++++++++++++----
+ gcc/config/m68k/amigaos.h | 21 +++----
+ gcc/config/m68k/amigaos.opt | 4 +-
+ gcc/config/m68k/m68k.c | 130 ++++++++++++++++++++++++++++--------------
+ gcc/config/m68k/m68k.md | 6 +-
+ gcc/config/m68k/m68kamigaos.h | 23 ++++++++
+ gcc/config/m68k/predicates.md | 4 ++
+ 8 files changed, 170 insertions(+), 71 deletions(-)
+
+diff --git a/gcc/BASE-VER b/gcc/BASE-VER
+index b557a4031409..6352d5267189 100644
+--- gcc/BASE-VER
++++ gcc/BASE-VER
+@@ -1 +1 @@
+-6.3.1a
++6.3.1b
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index 916140bdc628..81d08245b580 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -548,13 +548,13 @@ _m68k_function_arg (CUMULATIVE_ARGS *cump, machine_mode mode, const_tree type)
+ }
+ }
+
+-// if (reg == AMIGAOS_MAX_REGPARM && altregbegin != -1)
+-// {
+-// DPRINTF(("look for alt reg\n"));
+-// regbegin = altregbegin;
+-// altregbegin = -1;
+-// goto look_for_reg;
+-// }
++ if (reg == AMIGAOS_MAX_REGPARM && altregbegin != -1)
++ {
++ DPRINTF(("look for alt reg\n"));
++ regbegin = altregbegin;
++ altregbegin = -1;
++ goto look_for_reg;
++ }
+ }
+
+ if (cum->last_arg_reg != -1)
+@@ -775,9 +775,10 @@ amigaos_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno,
+ int *total, bool speed)
+ {
+ // DPRINTF(("outer: %d, opno: %d", outer_code, opno));
+-// debug_rtx(x);
+ bool r = m68k_rtx_costs (x, mode, outer_code, opno, total, speed);
+- *total *= 4;
++// *total *= 4;
++// fprintf(stderr, "costs: %d, mode=%d, outer=%d, opno=%d, speed=%d, ok=%d\n", *total * 4, mode, outer_code, opno, speed, r);
++// debug_rtx(x);
+ return r;
+ }
+
+@@ -789,7 +790,37 @@ amiga_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_U
+ {
+ if (0 == strncmp(".text", name, 5))
+ name = ".text";
+-// fprintf (asm_out_file, "\t.section\t%s\n", name);
+ fprintf (asm_out_file, "\t%s\n", name);
+ }
+
++/* Baserel support. */
++
++/**
++ * Does x reference the pic_reg and is const or plus?
++ */
++int amiga_is_const_pic_ref(const_rtx x)
++{
++ const_rtx y = x;
++ if (flag_pic < 3)
++ return false;
++ while (GET_CODE(y) == CONST || GET_CODE(y) == PLUS)
++ y = XEXP(y, 0);
++ return (x != y && REG_P(y) && REGNO(y) == PIC_REG);
++}
++
++
++/* Does operand (which is a symbolic_operand) live in text space? If
++ so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true.
++
++ This function is used in base relative code generation. */
++
++int
++read_only_operand (rtx operand)
++{
++ if (GET_CODE (operand) == CONST)
++ operand = XEXP (XEXP (operand, 0), 0);
++ if (GET_CODE (operand) == SYMBOL_REF)
++ return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand);
++ return 1;
++}
++
+diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h
+index afc2c6563143..9820f0ed1219 100644
+--- gcc/config/m68k/amigaos.h
++++ gcc/config/m68k/amigaos.h
+@@ -221,18 +221,6 @@ while (0)
+
+ #if 0
+
+-/* Baserel support. */
+-
+-/* Given that symbolic_operand(X), return TRUE if no special
+- base relative relocation is necessary */
+-
+-#define LEGITIMATE_BASEREL_OPERAND_P(X) \
+- (flag_pic >= 3 && read_only_operand (X))
+-
+-#undef LEGITIMATE_PIC_OPERAND_P
+-#define LEGITIMATE_PIC_OPERAND_P(X) \
+- (! symbolic_operand (X, VOIDmode) || LEGITIMATE_BASEREL_OPERAND_P (X))
+-
+ /* Define this macro if references to a symbol must be treated
+ differently depending on something about the variable or
+ function named by the symbol (such as what section it is in).
+@@ -492,3 +480,12 @@ while (0)
+ bool
+ amigaos_rtx_costs (rtx, machine_mode, int, int, int *, bool);
+
++/* SBF: macro to test for const via pic_reg. */
++#define CONST_PLUS_PIC_REG_CONST_UNSPEC_P(x) \
++ (GET_CODE(x) == CONST \
++ && GET_CODE(XEXP(x, 0)) == PLUS \
++ && REG_P(XEXP(XEXP(x, 0), 0)) \
++ && REGNO(XEXP(XEXP(x, 0), 0)) == PIC_REG \
++ && GET_CODE(XEXP(XEXP(x, 0), 1)) == CONST \
++ && GET_CODE(XEXP(XEXP(XEXP(x, 0), 1), 0)) == UNSPEC \
++ )
+diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt
+index 1faa3f2eeb26..4d9a42052355 100644
+--- gcc/config/m68k/amigaos.opt
++++ gcc/config/m68k/amigaos.opt
+@@ -12,11 +12,11 @@ Target RejectNegative Var(flag_smallcode,1)
+ small code model
+
+ fbaserel
+-Target Common Report Var(flag_mybaserel,1)
++Target Report Var(flag_pic,3)
+ data is adressed relativ to a4
+
+ fbaserel32
+-Target Common Report Var(flag_mybaserel,2)
++Target Report Var(flag_pic,4)
+ data is adressed relativ to a4 with 32 bit offsets
+
+ resident
+diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
+index b6ef99024ea6..64dcbf6969ee 100644
+--- gcc/config/m68k/m68k.c
++++ gcc/config/m68k/m68k.c
+@@ -591,7 +591,8 @@ m68k_option_override (void)
+ if (TARGET_PCREL && flag_pic == 0)
+ flag_pic = 1;
+
+- if (!flag_pic)
++ /* SBF: use normal jumps/calls with baserel(32) modes. */
++ if (!flag_pic || flag_pic > 2)
+ {
+ m68k_symbolic_call_var = M68K_SYMBOLIC_CALL_JSR;
+
+@@ -888,8 +889,9 @@ m68k_save_reg (unsigned int regno, bool interrupt_handler)
+ {
+ if (crtl->saves_all_registers)
+ return true;
++ /* SBF: do not save the PIC_REG with baserel(32) modes. */
+ if (crtl->uses_pic_offset_table)
+- return true;
++ return flag_pic < 3;
+ /* Reload may introduce constant pool references into a function
+ that thitherto didn't need a PIC register. Note that the test
+ above will not catch that case because we will only set
+@@ -1149,8 +1151,9 @@ m68k_expand_prologue (void)
+ current_frame.reg_mask, true, true));
+ }
+
++ /* SBF: do not load the PIC_REG with baserel(32) */
+ if (!TARGET_SEP_DATA
+- && crtl->uses_pic_offset_table)
++ && crtl->uses_pic_offset_table && flag_pic < 3)
+ emit_insn (gen_load_got (pic_offset_table_rtx));
+ }
+
+@@ -2135,6 +2138,12 @@ m68k_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
+ {
+ struct m68k_address address;
+
++#ifdef TARGET_AMIGA
++ /* SBF: the baserel(32) const plus pic_ref, symbol is an address. */
++ if (amiga_is_const_pic_ref(x))
++ return true;
++#endif
++
+ return m68k_decompose_address (mode, x, strict_p, &address);
+ }
+
+@@ -2468,9 +2477,33 @@ legitimize_pic_address (rtx orig, machine_mode mode ATTRIBUTE_UNUSED,
+ if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
+ {
+ gcc_assert (reg);
+- pic_ref = m68k_wrap_symbol_into_got_ref (orig, RELOC_GOT, reg);
+- pic_ref = m68k_move_to_reg (pic_ref, orig, reg);
+-// debug_rtx(pic_ref);
++ if (flag_pic < 3)
++ {
++ pic_ref = m68k_wrap_symbol_into_got_ref (orig, RELOC_GOT, reg);
++ pic_ref = m68k_move_to_reg (pic_ref, orig, reg);
++ }
++ #ifdef TARGET_AMIGA
++ else
++ {
++ tree decl = SYMBOL_REF_DECL (orig);
++
++ /* SBF: Does the symbol use common or bss and qualifies for pic_reg?
++ * Do not ref to .text via pic_reg!
++ */
++ if (!SYMBOL_REF_FUNCTION_P(orig) && decl && (DECL_COMMON (decl) || bss_initializer_p (decl)))
++ {
++ /* SBF: unfortunately using the wrapped symbol without MEM does not work.
++ * The pic_ref reference gets decomposed and leads to no working code.
++ */
++ pic_ref = m68k_wrap_symbol (pic_ref, RELOC_GOT, m68k_get_gp (), reg);
++
++ /* SBF: adding const avoids decomposing. */
++ pic_ref = gen_rtx_CONST (Pmode, pic_ref);
++ }
++ else
++ pic_ref = gen_rtx_CONST (Pmode, pic_ref);
++ }
++#endif
+ }
+ else if (GET_CODE (orig) == CONST)
+ {
+@@ -2489,7 +2522,8 @@ legitimize_pic_address (rtx orig, machine_mode mode ATTRIBUTE_UNUSED,
+ orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
+ base == reg ? 0 : reg);
+
+- if (GET_CODE (orig) == CONST_INT)
++ /* SBF: use normal plus and rely on optimizer with baserel(32). */
++ if (flag_pic < 3 && GET_CODE (orig) == CONST_INT)
+ pic_ref = plus_constant (Pmode, base, INTVAL (orig));
+ else
+ pic_ref = gen_rtx_PLUS (Pmode, base, orig);
+@@ -4453,7 +4487,6 @@ floating_exact_log2 (rtx x)
+ void
+ print_operand (FILE *file, rtx op, int letter)
+ {
+-// printf("letter: %c\n", letter);
+ if (letter == '.')
+ {
+ if (MOTOROLA)
+@@ -4486,7 +4519,9 @@ print_operand (FILE *file, rtx op, int letter)
+ else if (letter == 'p')
+ {
+ output_addr_const (file, op);
+- if (!(GET_CODE (op) == SYMBOL_REF && SYMBOL_REF_LOCAL_P (op)))
++ /* SBF: do not add @PLTPC with baserel(32). */
++ if (flag_pic < 3
++ && !(GET_CODE (op) == SYMBOL_REF && SYMBOL_REF_LOCAL_P (op)))
+ fprintf (file, "@PLTPC");
+ }
+ else if (GET_CODE (op) == REG)
+@@ -4505,10 +4540,12 @@ print_operand (FILE *file, rtx op, int letter)
+ && CONSTANT_ADDRESS_P (XEXP (op, 0))
+ && !(GET_CODE (XEXP (op, 0)) == CONST_INT
+ && INTVAL (XEXP (op, 0)) < 0x8000
+- && INTVAL (XEXP (op, 0)) >= -0x8000))
++ && INTVAL (XEXP (op, 0)) >= -0x8000)
+ #ifdef TARGET_AMIGA
+- if (!flag_mybaserel)
++/* SBF: Do not append some 'l' with baserel(32). */
++ && !CONST_PLUS_PIC_REG_CONST_UNSPEC_P(XEXP(op, 0))
+ #endif
++ )
+ fprintf (file, MOTOROLA ? ".l" : ":l");
+ }
+ else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode)
+@@ -4554,9 +4591,18 @@ m68k_get_reloc_decoration (enum m68k_reloc reloc)
+ switch (reloc)
+ {
+ case RELOC_GOT:
+-// if (TARGET_AMIGA)
+-// return "";
+-// else
++ /* SBF: add the proper extension for baserel relocs with baserel(32). */
++ if (TARGET_AMIGA)
++ {
++ if (flag_pic == 1)
++ return ".w";
++ else if (flag_pic == 3)
++ return ":W";
++ else if (flag_pic == 4)
++ return ":L";
++ else
++ return "";
++ }
+ if (MOTOROLA)
+ {
+ if (flag_pic == 1 && TARGET_68020)
+@@ -4707,6 +4753,22 @@ print_operand_address (FILE *file, rtx addr)
+ {
+ struct m68k_address address;
+
++#ifdef TARGET_AMIGA
++ /*
++ * SBF: remove the const wrapper.
++ */
++ if (CONST_PLUS_PIC_REG_CONST_UNSPEC_P(addr))
++ {
++ print_operand_address(file, XEXP(addr, 0));
++ return;
++ }
++ if (symbolic_operand(addr, VOIDmode))
++ {
++ memset (&address, 0, sizeof (address));
++ address.offset = addr;
++ }
++ else
++#endif
+ if (!m68k_decompose_address (QImode, addr, true, &address))
+ gcc_unreachable ();
+
+@@ -4757,31 +4819,6 @@ print_operand_address (FILE *file, rtx addr)
+ if (flag_smallcode)
+ asm_fprintf(file, ":w(pc)");
+ }
+- else if (flag_mybaserel)
+- {
+- /* search the decl. */
+- tree decl = SYMBOL_REF_DECL (addr);
+- if (!decl)
+- {
+- rtx x = XEXP(addr, 0);
+- if (CONSTANT_POOL_ADDRESS_P(x))
+- decl = SYMBOL_REF_DECL (x);
+- if (!decl)
+- {
+- x = XEXP(x, 0);
+- decl = SYMBOL_REF_DECL (x);
+- }
+- }
+-
+- /* Qualifies for a4 if common or bss. Do not ref to .text! */
+- if (decl && (DECL_COMMON (decl) || bss_initializer_p (decl)))
+- {
+- if (flag_mybaserel == 1)
+- asm_fprintf (file, ":W(a4)");
+- else if (flag_mybaserel == 2)
+- asm_fprintf (file, ":L(a4)");
+- }
+- }
+ #endif
+ }
+ }
+@@ -5224,7 +5261,9 @@ m68k_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
+
+ /* Value is true if hard register REGNO can hold a value of machine-mode
+ MODE. On the 68000, we let the cpu registers can hold any mode, but
+- restrict the 68881 registers to floating-point modes. */
++ restrict the 68881 registers to floating-point modes.
++ SBF: Disallow the frame pointer register, if the frame pointer is used.
++ */
+
+ bool
+ m68k_regno_mode_ok (int regno, machine_mode mode)
+@@ -5233,12 +5272,12 @@ m68k_regno_mode_ok (int regno, machine_mode mode)
+ {
+ /* Data Registers, can hold aggregate if fits in. */
+ if (regno + GET_MODE_SIZE (mode) / 4 <= 8)
+- return true;
++ return !flag_omit_frame_pointer || regno != FRAME_POINTER_REGNUM;
+ }
+ else if (ADDRESS_REGNO_P (regno))
+ {
+ if (regno + GET_MODE_SIZE (mode) / 4 <= 16)
+- return true;
++ return !flag_omit_frame_pointer || regno != FRAME_POINTER_REGNUM;
+ }
+ else if (FP_REGNO_P (regno))
+ {
+@@ -5259,6 +5298,13 @@ m68k_secondary_reload_class (enum reg_class rclass,
+ machine_mode mode, rtx x)
+ {
+ int regno;
++#ifdef TARGET_AMIGA
++ /* SBF: check for baserel's const pic_ref
++ * and return ADDR_REGS or NO_REGS
++ */
++ if (!MEM_P(x) && amiga_is_const_pic_ref(x))
++ return rclass == ADDR_REGS ? NO_REGS : ADDR_REGS;
++#endif
+
+ regno = true_regnum (x);
+
+diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
+index f5b63f43c372..24332476b91b 100644
+--- gcc/config/m68k/m68k.md
++++ gcc/config/m68k/m68k.md
+@@ -128,13 +128,11 @@
+ (UNSPECV_TAS_2 4)
+ ])
+
+-;; Registers by name.
++;; Registers by name. SBF: Do not define PIC_REG / A6_REG here!
+ (define_constants
+ [(D0_REG 0)
+ (A0_REG 8)
+ (A1_REG 9)
+- (PIC_REG 13)
+- (A6_REG 14)
+ (SP_REG 15)
+ (FP0_REG 16)
+ ])
+@@ -502,7 +500,7 @@
+ [(set (cc0)
+ (compare (match_operand:SI 0 "nonimmediate_operand" "rKT,rKs,mr,ma,>")
+ (match_operand:SI 1 "general_operand" "mr,ma,KTr,Ksr,>")))]
+- "!TARGET_COLDFIRE"
++ "!TARGET_COLDFIRE && (flag_pic < 3 || GET_CODE(operands[1]) != CONST || GET_CODE(XEXP(operands[1], 0)) != PLUS || !REG_P(XEXP(XEXP(operands[1], 0), 0)) || REGNO(XEXP(XEXP(operands[1], 0), 0)) != PIC_REG)"
+ {
+ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+ return "cmpm%.l %1,%0";
+diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h
+index 539d5f0bf934..74403a50bb67 100644
+--- gcc/config/m68k/m68kamigaos.h
++++ gcc/config/m68k/m68kamigaos.h
+@@ -578,3 +578,26 @@ amigaos_prelink_hook((const char **)(LD1_ARGV), (STRIP))
+
+ // this disables tree_loop_distribute_patterns
+ #define C_COMMON_OVERRIDE_OPTIONS flag_no_builtin = 1
++/* Baserel support. */
++
++extern int amiga_is_const_pic_ref(const_rtx x);
++
++#undef CONSTANT_ADDRESS_P
++#define CONSTANT_ADDRESS_P(X) \
++((GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \
++ || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST \
++ || GET_CODE (X) == HIGH \
++ ) && !amiga_is_const_pic_ref(X))
++
++
++/* Given that symbolic_operand(X), return TRUE if no special
++ base relative relocation is necessary */
++
++#define LEGITIMATE_BASEREL_OPERAND_P(X) \
++ (flag_pic >= 3 && read_only_operand (X))
++
++#undef LEGITIMATE_PIC_OPERAND_P
++#define LEGITIMATE_PIC_OPERAND_P(X) ( \
++ ! symbolic_operand (X, VOIDmode) || LEGITIMATE_BASEREL_OPERAND_P (X))
++
++// (GET_CODE(X) == CONST && (GET_CODE(XEXP(X, 0)) == SYMBOL_REF || GET_CODE(XEXP(X, 0)) == LABEL_REF) && !CONSTANT_POOL_ADDRESS_P (XEXP(X, 0))) ||
+diff --git a/gcc/config/m68k/predicates.md b/gcc/config/m68k/predicates.md
+index 186436c42b77..9533e65ceaab 100644
+--- gcc/config/m68k/predicates.md
++++ gcc/config/m68k/predicates.md
+@@ -30,6 +30,10 @@
+ || GET_CODE (XEXP (op, 0)) == LABEL_REF
+ || GET_CODE (XEXP (op, 0)) == CONST))
+ return 1;
++#ifdef TARGET_AMIGA
++ if (flag_pic >= 3 && amiga_is_const_pic_ref(op))
++ return 0;
++#endif
+ return general_operand (op, mode);
+ })
+
+
+From e74ef22307cef4b728ea06a9bb78f24d3c7879d6 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 20 Mar 2017 22:47:47 +0100
+Subject: [PATCH 033/303] @R improved register renamingRegister renaming now
+ updates the register ref count. Also the stack variable creation is scheduled
+ later, to omitt push/pop of unused variables.The regs d0/a0 are preferred and
+ rarely renamed.
+
+---
+ gcc/calls.c | 2 +-
+ gcc/config/m68k/amigaos.c | 9 +++++
+ gcc/config/m68k/amigaos.h | 5 +++
+ gcc/config/m68k/m68k.c | 12 ++++---
+ gcc/config/m68k/m68k.h | 10 +++---
+ gcc/df-scan.c | 7 ++++
+ gcc/doc/tm.texi | 4 +++
+ gcc/doc/tm.texi.in | 2 ++
+ gcc/expr.c | 2 +-
+ gcc/passes.def | 6 ++--
+ gcc/regrename.c | 84 +++++++++++++++++++++++++++--------------------
+ gcc/target.def | 19 +++++++++++
+ gcc/targhooks.c | 7 ++++
+ gcc/targhooks.h | 1 +
+ 14 files changed, 120 insertions(+), 50 deletions(-)
+
+diff --git a/gcc/calls.c b/gcc/calls.c
+index 730d82e65cf3..c78059fb5199 100644
+--- gcc/calls.c
++++ gcc/calls.c
+@@ -21,12 +21,12 @@ along with GCC; see the file COPYING3. If not see
+ #include "system.h"
+ #include "coretypes.h"
+ #include "backend.h"
+-#include "tm_p.h"
+ #include "target.h"
+ #include "rtl.h"
+ #include "tree.h"
+ #include "gimple.h"
+ #include "predict.h"
++#include "tm_p.h"
+ #include "stringpool.h"
+ #include "expmed.h"
+ #include "optabs.h"
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index 81d08245b580..88205e25476e 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -824,3 +824,12 @@ read_only_operand (rtx operand)
+ return 1;
+ }
+
++reg_class_t
++amiga_preferred_rename_class2(reg_class_t rclass ATTRIBUTE_UNUSED, int regno )
++{
++ if (regno == 0)
++ return D0_REGS;
++ if (regno == 8)
++ return A0_REGS;
++ return regno_reg_class[regno];
++}
+diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h
+index 9820f0ed1219..7259611edc9e 100644
+--- gcc/config/m68k/amigaos.h
++++ gcc/config/m68k/amigaos.h
+@@ -489,3 +489,8 @@ amigaos_rtx_costs (rtx, machine_mode, int, int, int *, bool);
+ && GET_CODE(XEXP(XEXP(x, 0), 1)) == CONST \
+ && GET_CODE(XEXP(XEXP(XEXP(x, 0), 1), 0)) == UNSPEC \
+ )
++
++#undef TARGET_PREFERRED_RENAME_CLASS2
++#define TARGET_PREFERRED_RENAME_CLASS2 amiga_preferred_rename_class2
++reg_class_t
++amiga_preferred_rename_class2(reg_class_t, int);
+diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
+index 64dcbf6969ee..d60371a92bc6 100644
+--- gcc/config/m68k/m68k.c
++++ gcc/config/m68k/m68k.c
+@@ -801,9 +801,11 @@ m68k_compute_frame_layout (void)
+
+ /* Only compute the frame once per function.
+ Don't cache information until reload has been completed. */
+- if (current_frame.funcdef_no == current_function_funcdef_no
+- && reload_completed)
+- return;
++ /* SBF: No. Register renaming may free some variables,
++ * => compute it again and again... */
++// if (current_frame.funcdef_no == current_function_funcdef_no
++// && reload_completed)
++// return;
+
+ current_frame.size = (get_frame_size () + 3) & -4;
+
+@@ -5272,12 +5274,12 @@ m68k_regno_mode_ok (int regno, machine_mode mode)
+ {
+ /* Data Registers, can hold aggregate if fits in. */
+ if (regno + GET_MODE_SIZE (mode) / 4 <= 8)
+- return !flag_omit_frame_pointer || regno != FRAME_POINTER_REGNUM;
++ return true;
+ }
+ else if (ADDRESS_REGNO_P (regno))
+ {
+ if (regno + GET_MODE_SIZE (mode) / 4 <= 16)
+- return !flag_omit_frame_pointer || regno != FRAME_POINTER_REGNUM;
++ return !frame_pointer_needed || regno != FRAME_POINTER_REGNUM;
+ }
+ else if (FP_REGNO_P (regno))
+ {
+diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h
+index 74d5aa042059..5142adf24e4d 100644
+--- gcc/config/m68k/m68k.h
++++ gcc/config/m68k/m68k.h
+@@ -440,8 +440,8 @@ along with GCC; see the file COPYING3. If not see
+ /* The m68k has three kinds of registers, so eight classes would be
+ a complete set. One of them is not needed. */
+ enum reg_class {
+- NO_REGS, DATA_REGS,
+- ADDR_REGS, FP_REGS,
++ NO_REGS, DATA_REGS, D0_REGS,
++ ADDR_REGS, A0_REGS, FP_REGS,
+ GENERAL_REGS, DATA_OR_FP_REGS,
+ ADDR_OR_FP_REGS, ALL_REGS,
+ LIM_REG_CLASSES };
+@@ -449,8 +449,8 @@ enum reg_class {
+ #define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+ #define REG_CLASS_NAMES \
+- { "NO_REGS", "DATA_REGS", \
+- "ADDR_REGS", "FP_REGS", \
++ { "NO_REGS", "DATA_REGS", "D0_REGS" \
++ "ADDR_REGS", "A0_REGS", "FP_REGS", \
+ "GENERAL_REGS", "DATA_OR_FP_REGS", \
+ "ADDR_OR_FP_REGS", "ALL_REGS" }
+
+@@ -458,7 +458,9 @@ enum reg_class {
+ { \
+ {0x00000000}, /* NO_REGS */ \
+ {0x000000ff}, /* DATA_REGS */ \
++ {0x00000001}, /* D0_REGS */ \
+ {0x0100ff00}, /* ADDR_REGS */ \
++ {0x00000100}, /* A0_REGS */ \
+ {0x00ff0000}, /* FP_REGS */ \
+ {0x0100ffff}, /* GENERAL_REGS */ \
+ {0x00ff00ff}, /* DATA_OR_FP_REGS */ \
+diff --git a/gcc/df-scan.c b/gcc/df-scan.c
+index 98de84405428..b0ef0813d07d 100644
+--- gcc/df-scan.c
++++ gcc/df-scan.c
+@@ -1807,6 +1807,13 @@ df_ref_change_reg_with_loc_1 (struct df_reg_info *old_df,
+ df_ref *ref_ptr;
+ struct df_insn_info *insn_info = DF_REF_INSN_INFO (the_ref);
+
++ if (DF_REF_FLAGS_IS_SET(the_ref, DF_HARD_REG_LIVE))
++ {
++ if (DF_REF_REGNO(the_ref) < FIRST_PSEUDO_REGISTER)
++ --df->hard_regs_live_count[DF_REF_REGNO(the_ref)];
++ ++df->hard_regs_live_count[new_regno];
++ }
++
+ DF_REF_REGNO (the_ref) = new_regno;
+ DF_REF_REG (the_ref) = regno_reg_rtx[new_regno];
+
+diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
+index 745910f9a331..6604514427fa 100644
+--- gcc/doc/tm.texi
++++ gcc/doc/tm.texi
+@@ -2489,6 +2489,10 @@ only if neither labeling works.
+ A target hook that places additional preference on the register class to use when it is necessary to rename a register in class @var{rclass} to another class, or perhaps @var{NO_REGS}, if no preferred register class is found or hook @code{preferred_rename_class} is not implemented. Sometimes returning a more restrictive class makes better code. For example, on ARM, thumb-2 instructions using @code{LO_REGS} may be smaller than instructions using @code{GENERIC_REGS}. By returning @code{LO_REGS} from @code{preferred_rename_class}, code size can be reduced.
+ @end deftypefn
+
++@deftypefn {Target Hook} reg_class_t TARGET_PREFERRED_RENAME_CLASS2 (reg_class_t @var{rclass}, int @var{regno})
++A target hook that places additional preference on the register class to use when it is necessary to rename a register in class @var{rclass} to another class, or perhaps @var{NO_REGS}, if no preferred register class is found or hook @code{preferred_rename_class2} is not implemented. Sometimes returning a more restrictive class makes better code. For example, on ARM, thumb-2 instructions using @code{LO_REGS} may be smaller than instructions using @code{GENERIC_REGS}. By returning @code{LO_REGS} from @code{preferred_rename_class2}, code size can be reduced.
++@end deftypefn
++
+ @deftypefn {Target Hook} reg_class_t TARGET_PREFERRED_RELOAD_CLASS (rtx @var{x}, reg_class_t @var{rclass})
+ A target hook that places additional restrictions on the register class
+ to use when it is necessary to copy value @var{x} into a register in class
+diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
+index f31c763991c5..e4da2a94249b 100644
+--- gcc/doc/tm.texi.in
++++ gcc/doc/tm.texi.in
+@@ -2281,6 +2281,8 @@ only if neither labeling works.
+
+ @hook TARGET_PREFERRED_RENAME_CLASS
+
++@hook TARGET_PREFERRED_RENAME_CLASS2
++
+ @hook TARGET_PREFERRED_RELOAD_CLASS
+
+ @defmac PREFERRED_RELOAD_CLASS (@var{x}, @var{class})
+diff --git a/gcc/expr.c b/gcc/expr.c
+index 01fe6437da12..6260f5ed7ed2 100644
+--- gcc/expr.c
++++ gcc/expr.c
+@@ -21,12 +21,12 @@ along with GCC; see the file COPYING3. If not see
+ #include "system.h"
+ #include "coretypes.h"
+ #include "backend.h"
+-#include "tm_p.h"
+ #include "target.h"
+ #include "rtl.h"
+ #include "tree.h"
+ #include "gimple.h"
+ #include "predict.h"
++#include "tm_p.h"
+ #include "ssa.h"
+ #include "expmed.h"
+ #include "optabs.h"
+diff --git a/gcc/passes.def b/gcc/passes.def
+index 7aed14445429..ec796082ae7f 100644
+--- gcc/passes.def
++++ gcc/passes.def
+@@ -447,9 +447,6 @@ along with GCC; see the file COPYING3. If not see
+ NEXT_PASS (pass_ree);
+ NEXT_PASS (pass_compare_elim_after_reload);
+ NEXT_PASS (pass_branch_target_load_optimize1);
+- NEXT_PASS (pass_thread_prologue_and_epilogue);
+- NEXT_PASS (pass_rtl_dse2);
+- NEXT_PASS (pass_stack_adjustments);
+ NEXT_PASS (pass_jump2);
+ NEXT_PASS (pass_duplicate_computed_gotos);
+ NEXT_PASS (pass_sched_fusion);
+@@ -457,6 +454,9 @@ along with GCC; see the file COPYING3. If not see
+ NEXT_PASS (pass_if_after_reload);
+ NEXT_PASS (pass_regrename);
+ NEXT_PASS (pass_cprop_hardreg);
++ NEXT_PASS (pass_thread_prologue_and_epilogue);
++ NEXT_PASS (pass_rtl_dse2);
++ NEXT_PASS (pass_stack_adjustments);
+ NEXT_PASS (pass_fast_rtl_dce);
+ NEXT_PASS (pass_reorder_blocks);
+ NEXT_PASS (pass_branch_target_load_optimize2);
+diff --git a/gcc/regrename.c b/gcc/regrename.c
+index df4c320700c5..ca7e24774afd 100644
+--- gcc/regrename.c
++++ gcc/regrename.c
+@@ -370,32 +370,31 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class,
+
+ /* Compute preferred rename class of super union of all the classes
+ in the chain. */
+- preferred_class
+- = (enum reg_class) targetm.preferred_rename_class (super_class);
++ preferred_class = (enum reg_class) targetm.preferred_rename_class2 (
++ super_class, old_reg);
+
+ /* Pick and check the register from the tied chain iff the tied chain
+- is not renamed. */
++ is not renamed. */
+ if (this_head->tied_chain && !this_head->tied_chain->renamed
+- && check_new_reg_p (old_reg, this_head->tied_chain->regno,
+- this_head, *unavailable))
++ && check_new_reg_p (old_reg, this_head->tied_chain->regno, this_head,
++ *unavailable))
+ return this_head->tied_chain->regno;
+
+ /* If PREFERRED_CLASS is not NO_REGS, we iterate in the first pass
+- over registers that belong to PREFERRED_CLASS and try to find the
+- best register within the class. If that failed, we iterate in
+- the second pass over registers that don't belong to the class.
+- If PREFERRED_CLASS is NO_REGS, we iterate over all registers in
+- ascending order without any preference. */
++ over registers that belong to PREFERRED_CLASS and try to find the
++ best register within the class. If that failed, we iterate in
++ the second pass over registers that don't belong to the class.
++ If PREFERRED_CLASS is NO_REGS, we iterate over all registers in
++ ascending order without any preference. */
+ has_preferred_class = (preferred_class != NO_REGS);
+- for (pass = (has_preferred_class ? 0 : 1); pass < 2; pass++)
+ {
+ int new_reg;
+ for (new_reg = 0; new_reg < FIRST_PSEUDO_REGISTER; new_reg++)
+ {
+ if (has_preferred_class
+- && (pass == 0)
+- != TEST_HARD_REG_BIT (reg_class_contents[preferred_class],
+- new_reg))
++ && 0
++ == TEST_HARD_REG_BIT(reg_class_contents[preferred_class],
++ new_reg))
+ continue;
+
+ if (!check_new_reg_p (old_reg, new_reg, this_head, *unavailable))
+@@ -405,17 +404,13 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class,
+ return new_reg;
+
+ /* In the first pass, we force the renaming of registers that
+- don't belong to PREFERRED_CLASS to registers that do, even
+- though the latters were used not very long ago.
+- Also use a register if no best_new_reg was found till now */
+- if (((pass == 0)
+- && !TEST_HARD_REG_BIT (reg_class_contents[preferred_class],
+- best_new_reg))
+- || tick[best_new_reg] > tick[new_reg])
++ don't belong to PREFERRED_CLASS to registers that do, even
++ though the latters were used not very long ago.
++ Also use a register if no best_new_reg was found till now */
++ if ((tick[best_new_reg] > tick[new_reg]
++ || (old_reg == best_new_reg && new_reg < old_reg)))
+ best_new_reg = new_reg;
+ }
+- if (pass == 0 && best_new_reg != old_reg)
+- break;
+ }
+ return best_new_reg;
+ }
+@@ -955,7 +950,7 @@ regrename_analyze (bitmap bb_mask)
+ numbering in its subpatterns. */
+
+ bool
+-regrename_do_replace (struct du_head *head, int reg)
++regrename_do_replace (struct du_head *head, int regno)
+ {
+ struct du_chain *chain;
+ unsigned int base_regno = head->regno;
+@@ -963,19 +958,20 @@ regrename_do_replace (struct du_head *head, int reg)
+
+ for (chain = head->first; chain; chain = chain->next_use)
+ {
+- unsigned int regno = ORIGINAL_REGNO (*chain->loc);
+- struct reg_attrs *attr = REG_ATTRS (*chain->loc);
+- int reg_ptr = REG_POINTER (*chain->loc);
++ unsigned int orig_regno = ORIGINAL_REGNO(*chain->loc);
++ struct reg_attrs *attr = REG_ATTRS(*chain->loc);
++ int reg_ptr = REG_POINTER(*chain->loc);
+
+ if (DEBUG_INSN_P (chain->insn) && REGNO (*chain->loc) != base_regno)
+- validate_change (chain->insn, &(INSN_VAR_LOCATION_LOC (chain->insn)),
+- gen_rtx_UNKNOWN_VAR_LOC (), true);
++ validate_change (chain->insn, &(INSN_VAR_LOCATION_LOC(chain->insn)),
++ gen_rtx_UNKNOWN_VAR_LOC (),
++ true);
+ else
+ {
+- validate_change (chain->insn, chain->loc,
+- gen_raw_REG (GET_MODE (*chain->loc), reg), true);
+- if (regno >= FIRST_PSEUDO_REGISTER)
+- ORIGINAL_REGNO (*chain->loc) = regno;
++ validate_change (chain->insn, chain->loc,
++ gen_raw_REG (GET_MODE(*chain->loc), regno), true);
++ if (orig_regno >= FIRST_PSEUDO_REGISTER)
++ ORIGINAL_REGNO (*chain->loc) = orig_regno;
+ REG_ATTRS (*chain->loc) = attr;
+ REG_POINTER (*chain->loc) = reg_ptr;
+ }
+@@ -984,10 +980,26 @@ regrename_do_replace (struct du_head *head, int reg)
+ if (!apply_change_group ())
+ return false;
+
+- mode = GET_MODE (*head->first->loc);
++ mode = GET_MODE(*head->first->loc);
+ head->renamed = 1;
+- head->regno = reg;
+- head->nregs = hard_regno_nregs[reg][mode];
++ head->regno = regno;
++ head->nregs = hard_regno_nregs[regno][mode];
++
++ /* SBF: also update the current df info, move from base_regno -> regno. */
++ for (chain = head->first; chain; chain = chain->next_use)
++ {
++ /* undo regno patch - will be patched again */
++ if (REGNO (*chain->loc) == regno)
++ SET_REGNO(*chain->loc, base_regno);
++ df_ref_change_reg_with_loc (*chain->loc, regno);
++
++ SET_REGNO(*chain->loc, regno);
++ }
++
++ /* Mark the old regno as no longer used. */
++ if (!df->hard_regs_live_count[base_regno])
++ df_set_regs_ever_live (base_regno, false);
++
+ return true;
+ }
+
+diff --git a/gcc/target.def b/gcc/target.def
+index 20f2b32da1e9..d0208812d83b 100644
+--- gcc/target.def
++++ gcc/target.def
+@@ -5170,6 +5170,25 @@ DEFHOOK
+ reg_class_t, (reg_class_t rclass),
+ default_preferred_rename_class)
+
++/*A target hook that places additional preference on the register
++ class
++ */
++DEFHOOK
++(preferred_rename_class2,
++ "A target hook that places additional preference on the register\
++ class to use when it is necessary to rename a register in class\
++ @var{rclass} to another class, or perhaps @var{NO_REGS}, if no\
++ preferred register class is found or hook @code{preferred_rename_class2}\
++ is not implemented.\
++ Sometimes returning a more restrictive class makes better code. For\
++ example, on ARM, thumb-2 instructions using @code{LO_REGS} may be\
++ smaller than instructions using @code{GENERIC_REGS}. By returning\
++ @code{LO_REGS} from @code{preferred_rename_class2}, code size can\
++ be reduced.",
++ reg_class_t, (reg_class_t rclass, int regno),
++ default_preferred_rename_class2)
++
++
+ /* This target hook allows the backend to avoid unsafe substitution
+ during register allocation. */
+ DEFHOOK
+diff --git a/gcc/targhooks.c b/gcc/targhooks.c
+index a34227705d2b..e106af7b261d 100644
+--- gcc/targhooks.c
++++ gcc/targhooks.c
+@@ -1542,6 +1542,13 @@ default_preferred_rename_class (reg_class_t rclass ATTRIBUTE_UNUSED)
+ return NO_REGS;
+ }
+
++/* The default implementation of TARGET_PREFERRED_RENAME_CLASS2. */
++reg_class_t
++default_preferred_rename_class2 (reg_class_t rclass, int regno ATTRIBUTE_UNUSED)
++{
++ return targetm.preferred_rename_class(rclass);
++}
++
+ /* The default implementation of TARGET_CLASS_LIKELY_SPILLED_P. */
+
+ bool
+diff --git a/gcc/targhooks.h b/gcc/targhooks.h
+index 7687c39b53b5..0a21ef982a65 100644
+--- gcc/targhooks.h
++++ gcc/targhooks.h
+@@ -204,6 +204,7 @@ extern bool default_profile_before_prologue (void);
+ extern reg_class_t default_preferred_reload_class (rtx, reg_class_t);
+ extern reg_class_t default_preferred_output_reload_class (rtx, reg_class_t);
+ extern reg_class_t default_preferred_rename_class (reg_class_t rclass);
++extern reg_class_t default_preferred_rename_class2 (reg_class_t rclass, int regno);
+ extern bool default_class_likely_spilled_p (reg_class_t);
+ extern unsigned char default_class_max_nregs (reg_class_t, machine_mode);
+
+
+From 6b9057baef40c5661b35c995f764401a82fcf9b7 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 20 Mar 2017 23:11:56 +0100
+Subject: [PATCH 034/303] @B fix include order
+
+---
+ gcc/function.c | 2 +-
+ gcc/var-tracking.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/function.c b/gcc/function.c
+index e903b1bcdf65..c614f9b9c000 100644
+--- gcc/function.c
++++ gcc/function.c
+@@ -35,11 +35,11 @@ along with GCC; see the file COPYING3. If not see
+ #include "system.h"
+ #include "coretypes.h"
+ #include "backend.h"
+-#include "tm_p.h"
+ #include "target.h"
+ #include "rtl.h"
+ #include "tree.h"
+ #include "gimple-expr.h"
++#include "tm_p.h"
+ #include "cfghooks.h"
+ #include "df.h"
+ #include "stringpool.h"
+diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
+index 149c0c123804..ab9c0117b078 100644
+--- gcc/var-tracking.c
++++ gcc/var-tracking.c
+@@ -89,10 +89,10 @@
+ #include "system.h"
+ #include "coretypes.h"
+ #include "backend.h"
+-#include "tm_p.h"
+ #include "target.h"
+ #include "rtl.h"
+ #include "tree.h"
++#include "tm_p.h"
+ #include "cfghooks.h"
+ #include "alloc-pool.h"
+ #include "tree-pass.h"
+
+From 1176f20fb5eb00f735a1c1ad2bb9d005fdac44aa Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 21 Mar 2017 00:15:07 +0100
+Subject: [PATCH 035/303] @B fix pssible NPE
+
+---
+ gcc/regrename.c | 19 +++++++++++--------
+ 1 file changed, 11 insertions(+), 8 deletions(-)
+
+diff --git a/gcc/regrename.c b/gcc/regrename.c
+index ca7e24774afd..4a9b4c2735a1 100644
+--- gcc/regrename.c
++++ gcc/regrename.c
+@@ -986,15 +986,18 @@ regrename_do_replace (struct du_head *head, int regno)
+ head->nregs = hard_regno_nregs[regno][mode];
+
+ /* SBF: also update the current df info, move from base_regno -> regno. */
+- for (chain = head->first; chain; chain = chain->next_use)
+- {
+- /* undo regno patch - will be patched again */
+- if (REGNO (*chain->loc) == regno)
+- SET_REGNO(*chain->loc, base_regno);
+- df_ref_change_reg_with_loc (*chain->loc, regno);
++ if (base_regno < FIRST_PSEUDO_REGISTER && regno < FIRST_PSEUDO_REGISTER)
++ for (chain = head->first; chain; chain = chain->next_use)
++ {
++ if (DEBUG_INSN_P (chain->insn))
++ continue;
++ /* undo regno patch - will be patched again */
++ if (REGNO (*chain->loc) == regno)
++ SET_REGNO(*chain->loc, base_regno);
++ df_ref_change_reg_with_loc (*chain->loc, regno);
+
+- SET_REGNO(*chain->loc, regno);
+- }
++ SET_REGNO(*chain->loc, regno);
++ }
+
+ /* Mark the old regno as no longer used. */
+ if (!df->hard_regs_live_count[base_regno])
+
+From 5844c3b50f6c2e52c83592a41e570603450d47b4 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 22 Mar 2017 15:48:28 +0100
+Subject: [PATCH 036/303] @B decrement ref count correctly
+
+---
+ gcc/df-scan.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/gcc/df-scan.c b/gcc/df-scan.c
+index b0ef0813d07d..1f23452afe19 100644
+--- gcc/df-scan.c
++++ gcc/df-scan.c
+@@ -1809,8 +1809,7 @@ df_ref_change_reg_with_loc_1 (struct df_reg_info *old_df,
+
+ if (DF_REF_FLAGS_IS_SET(the_ref, DF_HARD_REG_LIVE))
+ {
+- if (DF_REF_REGNO(the_ref) < FIRST_PSEUDO_REGISTER)
+- --df->hard_regs_live_count[DF_REF_REGNO(the_ref)];
++ --df->hard_regs_live_count[DF_REF_REGNO(the_ref)];
+ ++df->hard_regs_live_count[new_regno];
+ }
+
+
+From e9a9e3005a6160dc5e9a4338c5516f3787e657da Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 22 Mar 2017 15:49:15 +0100
+Subject: [PATCH 037/303] @I cleanup
+
+---
+ gcc/regrename.c | 40 ++++++++++++++++++----------------------
+ 1 file changed, 18 insertions(+), 22 deletions(-)
+
+diff --git a/gcc/regrename.c b/gcc/regrename.c
+index 4a9b4c2735a1..2dd96db5b87f 100644
+--- gcc/regrename.c
++++ gcc/regrename.c
+@@ -356,8 +356,8 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class,
+ {
+ bool has_preferred_class;
+ enum reg_class preferred_class;
+- int pass;
+ int best_new_reg = old_reg;
++ int new_reg;
+
+ /* Further narrow the set of registers we can use for renaming.
+ If the chain needs a call-saved register, mark the call-used
+@@ -387,30 +387,26 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class,
+ If PREFERRED_CLASS is NO_REGS, we iterate over all registers in
+ ascending order without any preference. */
+ has_preferred_class = (preferred_class != NO_REGS);
++ for (new_reg = 0; new_reg < FIRST_PSEUDO_REGISTER; new_reg++)
+ {
+- int new_reg;
+- for (new_reg = 0; new_reg < FIRST_PSEUDO_REGISTER; new_reg++)
+- {
+- if (has_preferred_class
+- && 0
+- == TEST_HARD_REG_BIT(reg_class_contents[preferred_class],
+- new_reg))
+- continue;
++ if (has_preferred_class
++ && !TEST_HARD_REG_BIT(reg_class_contents[preferred_class],
++ new_reg))
++ continue;
+
+- if (!check_new_reg_p (old_reg, new_reg, this_head, *unavailable))
+- continue;
++ if (!check_new_reg_p (old_reg, new_reg, this_head, *unavailable))
++ continue;
+
+- if (!best_rename)
+- return new_reg;
++ if (!best_rename)
++ return new_reg;
+
+- /* In the first pass, we force the renaming of registers that
+- don't belong to PREFERRED_CLASS to registers that do, even
+- though the latters were used not very long ago.
+- Also use a register if no best_new_reg was found till now */
+- if ((tick[best_new_reg] > tick[new_reg]
+- || (old_reg == best_new_reg && new_reg < old_reg)))
+- best_new_reg = new_reg;
+- }
++ /* In the first pass, we force the renaming of registers that
++ don't belong to PREFERRED_CLASS to registers that do, even
++ though the latters were used not very long ago.
++ Also use a register if no best_new_reg was found till now */
++ if ((tick[best_new_reg] > tick[new_reg]
++ || (old_reg == best_new_reg && new_reg < old_reg)))
++ best_new_reg = new_reg;
+ }
+ return best_new_reg;
+ }
+@@ -989,7 +985,7 @@ regrename_do_replace (struct du_head *head, int regno)
+ if (base_regno < FIRST_PSEUDO_REGISTER && regno < FIRST_PSEUDO_REGISTER)
+ for (chain = head->first; chain; chain = chain->next_use)
+ {
+- if (DEBUG_INSN_P (chain->insn))
++ if (DEBUG_INSN_P (chain->insn) && VAR_LOC_UNKNOWN_P(INSN_VAR_LOCATION_LOC(chain->insn)))
+ continue;
+ /* undo regno patch - will be patched again */
+ if (REGNO (*chain->loc) == regno)
+
+From ed41bbc9c042c73e2c423a93d98b6c83988fc8e3 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 22 Mar 2017 16:02:57 +0100
+Subject: [PATCH 038/303] @R -ftree-loop-vectorize and -ftree-slp-vectorize are
+ no longer enabled with -O3
+
+---
+ gcc/opts.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/gcc/opts.c b/gcc/opts.c
+index 0f9431a0b323..28a617c0f14f 100644
+--- gcc/opts.c
++++ gcc/opts.c
+@@ -530,8 +530,10 @@ static const struct default_options default_options_table[] =
+ { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_finline_functions_called_once, NULL, 1 },
+ { OPT_LEVELS_3_PLUS, OPT_funswitch_loops, NULL, 1 },
+ { OPT_LEVELS_3_PLUS, OPT_fgcse_after_reload, NULL, 1 },
++#ifndef TARGET_AMIGA
+ { OPT_LEVELS_3_PLUS, OPT_ftree_loop_vectorize, NULL, 1 },
+ { OPT_LEVELS_3_PLUS, OPT_ftree_slp_vectorize, NULL, 1 },
++#endif
+ { OPT_LEVELS_3_PLUS, OPT_fvect_cost_model_, NULL, VECT_COST_MODEL_DYNAMIC },
+ { OPT_LEVELS_3_PLUS, OPT_fipa_cp_clone, NULL, 1 },
+ { OPT_LEVELS_3_PLUS, OPT_ftree_partial_pre, NULL, 1 },
+
+From 25f75fe3179ceb6da6f50b1c30d8fe810c1ccccd Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 22 Mar 2017 16:05:51 +0100
+Subject: [PATCH 039/303] @N added a new combine optimization.i2 something ->
+ regi3 reg -> somewherewithi4 compare reg, const_0is replaced with: something
+ -> somewhere, if the reg is dead at the comparison
+
+---
+ gcc/combine.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 60 insertions(+)
+
+diff --git a/gcc/combine.c b/gcc/combine.c
+index 75c6229766c0..333f8fef9655 100644
+--- gcc/combine.c
++++ gcc/combine.c
+@@ -102,6 +102,7 @@ along with GCC; see the file COPYING3. If not see
+ #include "valtrack.h"
+ #include "rtl-iter.h"
+ #include "print-rtl.h"
++#include "conditions.h"
+
+ #ifndef LOAD_EXTEND_OP
+ #define LOAD_EXTEND_OP(M) UNKNOWN
+@@ -2578,6 +2579,7 @@ static rtx_insn *
+ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
+ int *new_direct_jump_p, rtx_insn *last_combined_insn)
+ {
++ rtx_insn * del4 = 0;
+ /* New patterns for I3 and I2, respectively. */
+ rtx newpat, newi2pat = 0;
+ rtvec newpat_vec_with_clobbers = 0;
+@@ -3350,6 +3352,52 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
+ substed_i0 = 1;
+ }
+
++#if HAVE_cc0
++ /* SBF: This is an attempt to combine
++ * i2 something -> reg
++ * i3 reg -> somewhere
++ * with the next insn i4
++ * i4 compare reg, 0
++ *
++ * then
++ * newpat = something -> somewhere
++ *
++ * If the comparison with 0 is already done in the insn newpat
++ * and the reg is dead at the compare insn
++ * then perform the combine and mark the compare as deleted.
++ */
++ if (i2dest_killed && !i0 && !i1 && i2pat && i2_is_used + added_sets_2 > 1
++ && NEXT_INSN(i3))
++ {
++ rtx_insn *next = NEXT_INSN(i3);
++ rtx setn = single_set(next);
++ if (setn)
++ {
++ rtx srcn = SET_SRC(setn);
++ if (GET_CODE(srcn) == COMPARE)
++ {
++ rtx dstn = XEXP(srcn, 0);
++ srcn = XEXP(srcn, 1);
++
++ if (CONST_INT_P(srcn) && INTVAL(srcn) == 0
++ && find_reg_note(next, REG_DEAD, dstn))
++ {
++ /* now check via NOTICE_UPDATE_CC*/
++ NOTICE_UPDATE_CC(PATTERN(i2), i2);
++ if (cc_status.flags == 0 && rtx_equal_p(dstn, cc_status.value1))
++ {
++ added_sets_2 = 0;
++ i2_is_used = 0;
++
++ /* perform deletion later, if all other checks are ok. */
++ del4 = next;
++ }
++ }
++ }
++ }
++ }
++#endif
++
+ /* Fail if an autoincrement side-effect has been duplicated. Be careful
+ to count all the ways that I2SRC and I1SRC can be used. */
+ if ((FIND_REG_INC_NOTE (i2, NULL_RTX) != 0
+@@ -4387,6 +4435,18 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
+ move_deaths (newi2pat, NULL_RTX, from_luid, i2, &midnotes);
+ move_deaths (newpat, newi2pat, from_luid, i3, &midnotes);
+
++ /* SBF: perform the deletion of the next insn, if marked. */
++ if (del4)
++ {
++ int del_from_luid = DF_INSN_LUID(del4);
++ LOG_LINKS(del4) = NULL;
++ REG_NOTES(del4) = 0;
++ SET_INSN_DELETED(del4);
++ if (newi2pat)
++ move_deaths(newi2pat, NULL_RTX, del_from_luid, del4, &midnotes);
++ move_deaths(newpat, NULL_RTX, del_from_luid, del4, &midnotes);
++ }
++
+ /* Distribute all the LOG_LINKS and REG_NOTES from I1, I2, and I3. */
+ if (i3notes)
+ distribute_notes (i3notes, i3, i3, newi2pat ? i2 : NULL,
+
+From 464f34464d1abdb6e5dfcab0e78e12e15ca133b5 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 23 Mar 2017 16:12:37 +0100
+Subject: [PATCH 040/303] @B added further constraints to optimize the compare
+ away
+
+---
+ gcc/combine.c | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/gcc/combine.c b/gcc/combine.c
+index 333f8fef9655..1103521f9cf1 100644
+--- gcc/combine.c
++++ gcc/combine.c
+@@ -2598,7 +2598,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
+ I2 and not in I3, a REG_DEAD note must be made. */
+ rtx i3dest_killed = 0;
+ /* SET_DEST and SET_SRC of I2, I1 and I0. */
+- rtx i2dest = 0, i2src = 0, i1dest = 0, i1src = 0, i0dest = 0, i0src = 0;
++ rtx i3src = 0, i2dest = 0, i2src = 0, i1dest = 0, i1src = 0, i0dest = 0, i0src = 0;
+ /* Copy of SET_SRC of I1 and I0, if needed. */
+ rtx i1src_copy = 0, i0src_copy = 0, i0src_copy2 = 0;
+ /* Set if I2DEST was reused as a scratch register. */
+@@ -2632,6 +2632,9 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
+ if (i1 == i2 || i0 == i2 || (i0 && i0 == i1))
+ return 0;
+
++ if (single_set(i3))
++ i3src = SET_SRC(single_set(i3));
++
+ /* Only try four-insn combinations when there's high likelihood of
+ success. Look for simple insns, such as loads of constants or
+ binary operations involving a constant. */
+@@ -3367,6 +3370,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
+ * then perform the combine and mark the compare as deleted.
+ */
+ if (i2dest_killed && !i0 && !i1 && i2pat && i2_is_used + added_sets_2 > 1
++ && rtx_equal_p(i2dest, i3src)
+ && NEXT_INSN(i3))
+ {
+ rtx_insn *next = NEXT_INSN(i3);
+@@ -3391,7 +3395,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
+
+ /* perform deletion later, if all other checks are ok. */
+ del4 = next;
+- }
++ }
+ }
+ }
+ }
+@@ -4438,10 +4442,13 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
+ /* SBF: perform the deletion of the next insn, if marked. */
+ if (del4)
+ {
++// rtx set = SET_SRC(single_set(del4));
++
+ int del_from_luid = DF_INSN_LUID(del4);
+ LOG_LINKS(del4) = NULL;
+ REG_NOTES(del4) = 0;
+- SET_INSN_DELETED(del4);
++ SET_INSN_DELETED(del4);
++// XEXP(set, 0) = XEXP(set, 1);
+ if (newi2pat)
+ move_deaths(newi2pat, NULL_RTX, del_from_luid, del4, &midnotes);
+ move_deaths(newpat, NULL_RTX, del_from_luid, del4, &midnotes);
+
+From 704efeb80a44bf883699e620c4b51eef32d9659c Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 24 Mar 2017 17:05:33 +0100
+Subject: [PATCH 041/303] @N support -ramiga-... stuff
+
+---
+ gcc/config/m68k/amigaos.opt | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt
+index 4d9a42052355..f985cf5e2845 100644
+--- gcc/config/m68k/amigaos.opt
++++ gcc/config/m68k/amigaos.opt
+@@ -7,6 +7,18 @@ noixemul
+ Target RejectNegative
+ Do not use ixemul.library - use libnix instead to link
+
++ramiga-lib
++Target RejectNegative
++Use libinit.o as start file
++
++ramiga-libr
++Target RejectNegative
++Use libinitr.o as start file
++
++ramiga-dev
++Target RejectNegative
++Use devinit.o as start file
++
+ msmall-code
+ Target RejectNegative Var(flag_smallcode,1)
+ small code model
+
+From d62a4d349a55a59aa9d8b9a3f02827d66be960b4 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 24 Mar 2017 17:06:31 +0100
+Subject: [PATCH 042/303] @R make exception section name configurable by TARGET
+
+---
+ gcc/config/m68k/m68kamigaos.h | 6 ++++++
+ gcc/except.c | 4 ++--
+ gcc/target-def.h | 8 ++++++++
+ 3 files changed, 16 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h
+index 74403a50bb67..ececc6d76498 100644
+--- gcc/config/m68k/m68kamigaos.h
++++ gcc/config/m68k/m68kamigaos.h
+@@ -601,3 +601,9 @@ extern int amiga_is_const_pic_ref(const_rtx x);
+ ! symbolic_operand (X, VOIDmode) || LEGITIMATE_BASEREL_OPERAND_P (X))
+
+ // (GET_CODE(X) == CONST && (GET_CODE(XEXP(X, 0)) == SYMBOL_REF || GET_CODE(XEXP(X, 0)) == LABEL_REF) && !CONSTANT_POOL_ADDRESS_P (XEXP(X, 0))) ||
++
++#undef TARGET_GCC_EXCEPT_TABLE
++#define TARGET_GCC_EXCEPT_TABLE ".data"
++
++#undef TARGET_GCC_EXCEPT_TABLE_S
++#define TARGET_GCC_EXCEPT_TABLE_S ".data"
+diff --git a/gcc/except.c b/gcc/except.c
+index 2a1073f80cc4..156d7b76d249 100644
+--- gcc/except.c
++++ gcc/except.c
+@@ -2850,14 +2850,14 @@ switch_to_exception_section (const char * ARG_UNUSED (fnname))
+ it linkonce if we have COMDAT groups to tie them together. */
+ if (DECL_COMDAT_GROUP (current_function_decl) && HAVE_COMDAT_GROUP)
+ flags |= SECTION_LINKONCE;
+- sprintf (section_name, ".gcc_except_table.%s", fnname);
++ sprintf (section_name, TARGET_GCC_EXCEPT_TABLE_S, fnname);
+ s = get_section (section_name, flags, current_function_decl);
+ free (section_name);
+ }
+ else
+ #endif
+ exception_section
+- = s = get_section (".gcc_except_table", flags, NULL);
++ = s = get_section (TARGET_GCC_EXCEPT_TABLE, flags, NULL);
+ }
+ else
+ exception_section
+diff --git a/gcc/target-def.h b/gcc/target-def.h
+index ec5e09e568e6..9fbfde121095 100644
+--- gcc/target-def.h
++++ gcc/target-def.h
+@@ -108,3 +108,11 @@
+ #include "hooks.h"
+ #include "targhooks.h"
+ #include "insn-target-def.h"
++
++#ifndef TARGET_GCC_EXCEPT_TABLE
++#define TARGET_GCC_EXCEPT_TABLE ".gcc_except_table"
++#endif
++
++#ifndef TARGET_GCC_EXCEPT_TABLE_S
++#define TARGET_GCC_EXCEPT_TABLE_S ".gcc_except_table.%s"
++#endif
+
+From bd6fbbbc0a587184db27e691e05a795e1abdeaf6 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 24 Mar 2017 17:07:18 +0100
+Subject: [PATCH 043/303] @R build libstdc++-v3 with noiexmul
+
+---
+ libstdc++-v3/configure | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
+index 44ba3aca42af..d61b41b2fb7c 100755
+--- libstdc++-v3/configure
++++ libstdc++-v3/configure
+@@ -8636,6 +8636,8 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; }
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
++ enable_shared=no
++ CXXFLAGS="$CXXFLAGS -noixemul"
+ ;;
+ esac
+ ;;
+
+From f05e1e6bd5a30ee7dfea2399acf268771c986767 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sat, 25 Mar 2017 23:11:55 +0100
+Subject: [PATCH 044/303] @R move all EH data into .text section
+
+---
+ gcc/config/m68k/m68kamigaos.h | 7 +++++--
+ gcc/dwarf2out.c | 2 +-
+ 2 files changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h
+index ececc6d76498..68f3277bd87c 100644
+--- gcc/config/m68k/m68kamigaos.h
++++ gcc/config/m68k/m68kamigaos.h
+@@ -603,7 +603,10 @@ extern int amiga_is_const_pic_ref(const_rtx x);
+ // (GET_CODE(X) == CONST && (GET_CODE(XEXP(X, 0)) == SYMBOL_REF || GET_CODE(XEXP(X, 0)) == LABEL_REF) && !CONSTANT_POOL_ADDRESS_P (XEXP(X, 0))) ||
+
+ #undef TARGET_GCC_EXCEPT_TABLE
+-#define TARGET_GCC_EXCEPT_TABLE ".data"
++#define TARGET_GCC_EXCEPT_TABLE ".text"
+
+ #undef TARGET_GCC_EXCEPT_TABLE_S
+-#define TARGET_GCC_EXCEPT_TABLE_S ".data"
++#define TARGET_GCC_EXCEPT_TABLE_S ".text"
++
++#define EH_TABLES_CAN_BE_READ_ONLY 1
++
+diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
+index 995ae7f18758..2740e417b0b2 100644
+--- gcc/dwarf2out.c
++++ gcc/dwarf2out.c
+@@ -451,7 +451,7 @@ switch_to_eh_frame_section (bool back ATTRIBUTE_UNUSED)
+ /*global=*/1);
+ lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0,
+ /*global=*/0);
+- flags = ((! flag_pic
++ flags = (( (!flag_pic || flag_pic > 2)
+ || ((fde_encoding & 0x70) != DW_EH_PE_absptr
+ && (fde_encoding & 0x70) != DW_EH_PE_aligned
+ && (per_encoding & 0x70) != DW_EH_PE_absptr
+
+From 3be02d432149821fde6d3de2eca3830943c9dfc1 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 26 Mar 2017 20:49:43 +0200
+Subject: [PATCH 045/303] @R patches to work with amigaos-*-m68k
+
+---
+ libstdc++-v3/configure.host | 5 +++++
+ libstdc++-v3/include/c_global/cstdio | 2 --
+ 2 files changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/libstdc++-v3/configure.host b/libstdc++-v3/configure.host
+index 304a7f5aff61..354b1c7ead46 100644
+--- libstdc++-v3/configure.host
++++ libstdc++-v3/configure.host
+@@ -226,6 +226,11 @@ case "${host_os}" in
+ os_include_dir="os/generic"
+ atomicity_dir="cpu/generic"
+ ;;
++ amiga*)
++ os_include_dir="os/newlib"
++ CXXFLAGS="${CXXFLAGS} -noixemul"
++ CPPFLAGS="${CPPFLAGS} -noixemul"
++ ;;
+ bsd*)
+ # Plain BSD attempts to share FreeBSD files.
+ os_include_dir="os/bsd/freebsd"
+diff --git a/libstdc++-v3/include/c_global/cstdio b/libstdc++-v3/include/c_global/cstdio
+index 522d065d4dc6..86d524f96a62 100644
+--- libstdc++-v3/include/c_global/cstdio
++++ libstdc++-v3/include/c_global/cstdio
+@@ -149,9 +149,7 @@ namespace std
+ #if _GLIBCXX_USE_C99_STDIO
+
+ #undef snprintf
+-#ifndef AMIGA
+ #undef vfscanf
+-#endif
+ #undef vscanf
+ #undef vsnprintf
+ #undef vsscanf
+
+From 1a1c3869ddd0e8e75eef0849dcd0b060dd26cbbd Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 26 Mar 2017 20:50:20 +0200
+Subject: [PATCH 046/303] @R patches to work with amigaos-*-m68k
+
+---
+ libobjc/configure | 3 ++-
+ libobjc/objc/objc.h | 4 ++++
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/libobjc/configure b/libobjc/configure
+index 55fcc33dbe2d..a60258f422d8 100755
+--- libobjc/configure
++++ libobjc/configure
+@@ -7637,7 +7637,8 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; }
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+- lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
++ #lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
++ enable_shared=no
+ ;;
+ esac
+ ;;
+diff --git a/libobjc/objc/objc.h b/libobjc/objc/objc.h
+index 37391a446bb0..6c73f53290e8 100644
+--- libobjc/objc/objc.h
++++ libobjc/objc/objc.h
+@@ -52,7 +52,11 @@ extern "C" {
+ Important: this could change and we could switch to 'typedef bool
+ BOOL' in the future. Do not depend on the type of BOOL. */
+ #undef BOOL
++#ifdef AMIGA
++typedef short BOOL;
++#else
+ typedef unsigned char BOOL;
++#endif
+
+ #define YES (BOOL)1
+ #define NO (BOOL)0
+
+From 7f8948f412f79fb2efd6835a3062720c1b34febf Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 29 Mar 2017 18:08:05 +0200
+Subject: [PATCH 047/303] @B fix for possible corrupted code, due to combine
+ optimization. Maybe incorrect...
+
+---
+ gcc/reload1.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/reload1.c b/gcc/reload1.c
+index c2800f8cb790..7f386a3aaab0 100644
+--- gcc/reload1.c
++++ gcc/reload1.c
+@@ -7943,7 +7943,8 @@ do_input_reload (struct insn_chain *chain, struct reload *rl, int j)
+ AUTO_INC reload if reload_out is set but reload_out_reg isn't. */
+ && (! reload_inherited[j] || (rl->out && ! rl->out_reg))
+ && ! rtx_equal_p (reg_rtx, old)
+- && reg_rtx != 0)
++ && reg_rtx != 0
++ && rl->in_reg != rl->out_reg)
+ emit_input_reload_insns (chain, rld + j, old, j);
+
+ /* When inheriting a wider reload, we have a MEM in rl->in,
+
+From 709da5eaf06c7d9d1aa3332feab227469be4cc48 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 30 Mar 2017 11:29:16 +0200
+Subject: [PATCH 048/303] @B remove optimization The side effects are not
+ solved yet, so this experiment is removed from the 'stable' branch
+
+---
+ gcc/combine.c | 69 +----------------------------------------------------------
+ gcc/reload1.c | 3 +--
+ 2 files changed, 2 insertions(+), 70 deletions(-)
+
+diff --git a/gcc/combine.c b/gcc/combine.c
+index 1103521f9cf1..75c6229766c0 100644
+--- gcc/combine.c
++++ gcc/combine.c
+@@ -102,7 +102,6 @@ along with GCC; see the file COPYING3. If not see
+ #include "valtrack.h"
+ #include "rtl-iter.h"
+ #include "print-rtl.h"
+-#include "conditions.h"
+
+ #ifndef LOAD_EXTEND_OP
+ #define LOAD_EXTEND_OP(M) UNKNOWN
+@@ -2579,7 +2578,6 @@ static rtx_insn *
+ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
+ int *new_direct_jump_p, rtx_insn *last_combined_insn)
+ {
+- rtx_insn * del4 = 0;
+ /* New patterns for I3 and I2, respectively. */
+ rtx newpat, newi2pat = 0;
+ rtvec newpat_vec_with_clobbers = 0;
+@@ -2598,7 +2596,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
+ I2 and not in I3, a REG_DEAD note must be made. */
+ rtx i3dest_killed = 0;
+ /* SET_DEST and SET_SRC of I2, I1 and I0. */
+- rtx i3src = 0, i2dest = 0, i2src = 0, i1dest = 0, i1src = 0, i0dest = 0, i0src = 0;
++ rtx i2dest = 0, i2src = 0, i1dest = 0, i1src = 0, i0dest = 0, i0src = 0;
+ /* Copy of SET_SRC of I1 and I0, if needed. */
+ rtx i1src_copy = 0, i0src_copy = 0, i0src_copy2 = 0;
+ /* Set if I2DEST was reused as a scratch register. */
+@@ -2632,9 +2630,6 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
+ if (i1 == i2 || i0 == i2 || (i0 && i0 == i1))
+ return 0;
+
+- if (single_set(i3))
+- i3src = SET_SRC(single_set(i3));
+-
+ /* Only try four-insn combinations when there's high likelihood of
+ success. Look for simple insns, such as loads of constants or
+ binary operations involving a constant. */
+@@ -3355,53 +3350,6 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
+ substed_i0 = 1;
+ }
+
+-#if HAVE_cc0
+- /* SBF: This is an attempt to combine
+- * i2 something -> reg
+- * i3 reg -> somewhere
+- * with the next insn i4
+- * i4 compare reg, 0
+- *
+- * then
+- * newpat = something -> somewhere
+- *
+- * If the comparison with 0 is already done in the insn newpat
+- * and the reg is dead at the compare insn
+- * then perform the combine and mark the compare as deleted.
+- */
+- if (i2dest_killed && !i0 && !i1 && i2pat && i2_is_used + added_sets_2 > 1
+- && rtx_equal_p(i2dest, i3src)
+- && NEXT_INSN(i3))
+- {
+- rtx_insn *next = NEXT_INSN(i3);
+- rtx setn = single_set(next);
+- if (setn)
+- {
+- rtx srcn = SET_SRC(setn);
+- if (GET_CODE(srcn) == COMPARE)
+- {
+- rtx dstn = XEXP(srcn, 0);
+- srcn = XEXP(srcn, 1);
+-
+- if (CONST_INT_P(srcn) && INTVAL(srcn) == 0
+- && find_reg_note(next, REG_DEAD, dstn))
+- {
+- /* now check via NOTICE_UPDATE_CC*/
+- NOTICE_UPDATE_CC(PATTERN(i2), i2);
+- if (cc_status.flags == 0 && rtx_equal_p(dstn, cc_status.value1))
+- {
+- added_sets_2 = 0;
+- i2_is_used = 0;
+-
+- /* perform deletion later, if all other checks are ok. */
+- del4 = next;
+- }
+- }
+- }
+- }
+- }
+-#endif
+-
+ /* Fail if an autoincrement side-effect has been duplicated. Be careful
+ to count all the ways that I2SRC and I1SRC can be used. */
+ if ((FIND_REG_INC_NOTE (i2, NULL_RTX) != 0
+@@ -4439,21 +4387,6 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
+ move_deaths (newi2pat, NULL_RTX, from_luid, i2, &midnotes);
+ move_deaths (newpat, newi2pat, from_luid, i3, &midnotes);
+
+- /* SBF: perform the deletion of the next insn, if marked. */
+- if (del4)
+- {
+-// rtx set = SET_SRC(single_set(del4));
+-
+- int del_from_luid = DF_INSN_LUID(del4);
+- LOG_LINKS(del4) = NULL;
+- REG_NOTES(del4) = 0;
+- SET_INSN_DELETED(del4);
+-// XEXP(set, 0) = XEXP(set, 1);
+- if (newi2pat)
+- move_deaths(newi2pat, NULL_RTX, del_from_luid, del4, &midnotes);
+- move_deaths(newpat, NULL_RTX, del_from_luid, del4, &midnotes);
+- }
+-
+ /* Distribute all the LOG_LINKS and REG_NOTES from I1, I2, and I3. */
+ if (i3notes)
+ distribute_notes (i3notes, i3, i3, newi2pat ? i2 : NULL,
+diff --git a/gcc/reload1.c b/gcc/reload1.c
+index 7f386a3aaab0..c2800f8cb790 100644
+--- gcc/reload1.c
++++ gcc/reload1.c
+@@ -7943,8 +7943,7 @@ do_input_reload (struct insn_chain *chain, struct reload *rl, int j)
+ AUTO_INC reload if reload_out is set but reload_out_reg isn't. */
+ && (! reload_inherited[j] || (rl->out && ! rl->out_reg))
+ && ! rtx_equal_p (reg_rtx, old)
+- && reg_rtx != 0
+- && rl->in_reg != rl->out_reg)
++ && reg_rtx != 0)
+ emit_input_reload_insns (chain, rld + j, old, j);
+
+ /* When inheriting a wider reload, we have a MEM in rl->in,
+
+From c44d7bced301829dbab55b307545a7e029e69e6f Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 30 Mar 2017 20:44:57 +0200
+Subject: [PATCH 049/303] @N added a separate optimization pass
+
+---
+ gcc/Makefile.in | 1 +
+ gcc/bbb-opts.c | 401 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ gcc/passes.c | 27 ++++
+ gcc/passes.def | 1 +
+ gcc/regrename.c | 9 +-
+ gcc/tree-pass.h | 1 +
+ 6 files changed, 437 insertions(+), 3 deletions(-)
+ create mode 100755 gcc/bbb-opts.c
+ mode change 100644 => 100755 gcc/regrename.c
+
+diff --git a/gcc/Makefile.in b/gcc/Makefile.in
+index 575d308907cc..dc01aeef0f0c 100644
+--- gcc/Makefile.in
++++ gcc/Makefile.in
+@@ -1199,6 +1199,7 @@ OBJS = \
+ auto-inc-dec.o \
+ auto-profile.o \
+ bb-reorder.o \
++ bbb-opts.o \
+ bitmap.o \
+ bt-load.o \
+ builtins.o \
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+new file mode 100755
+index 000000000000..ff447c9e335e
+--- /dev/null
++++ gcc/bbb-opts.c
+@@ -0,0 +1,401 @@
++/* Bebbo's Optimizations.
++ Copyright (C) 2010-2016 Free Software Foundation, Inc.
++
++ This file is part of GCC.
++
++ GCC 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 3, or (at your option) any later
++ version.
++
++ GCC 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 GCC; see the file COPYING3. If not see
++ <http://www.gnu.org/licenses/>. */
++
++/**
++ * SBF (Stefan "Bebbo" Franke):
++ *
++ * This pass performs multiple optimizations.
++ *
++ * #1 propagate_moves
++ * check if a->b->a can be moved out of a loop.
++ *
++ * #2 strcpy
++ * move a,reg
++ * move reg,b
++ * cmp #0,reg
++ * jne/jeq
++ */
++
++#include "config.h"
++#include "system.h"
++#include "coretypes.h"
++#include "backend.h"
++#include "target.h"
++#include "rtl.h"
++#include "df.h"
++#include "tm_p.h"
++#include "insn-config.h"
++#include "recog.h"
++#include "cfgrtl.h"
++#include "emit-rtl.h"
++#include "tree-pass.h"
++#include "conditions.h"
++#include <vector>
++#include <map>
++
++extern void
++dump_insns (char const * name);
++
++/*
++ * #1 propagate a->b->a moves out of a loop.
++ *
++ * consider a loop:
++ *
++ * .L1
++ * ...
++ * move d0, a0 ; (1)
++ * ...
++ * move xy, (a0)+
++ * ...
++ * move a0, d0 ; (2)
++ * ...
++ * jxx .L1
++ *
++ * Then the statements (1) and (2) can be moved out of the loop:
++ *
++ * move d0, a0 ; (3)
++ * .L1
++ * ...
++ * move *, (a0)+ ; a0 is modified somehow
++ * ...
++ * jxx .L1
++ * move a0, d0 ; (4)
++ *
++ * if all criteria are met:
++ *
++ * a) no other jump to .L1 -> (LABEL_NUSES(insn) == 1)
++ * b) no other use of d0 inside the loop
++ * c) no other use of a0 before (1)
++ * d) no other use of a1 after (2)
++ *
++ * Optional:
++ * - omit (4) if d0 is dead
++ *
++ * this will e.g. convert
++ .L6:
++ move.l d0,a1
++ move.b (a1)+,d1
++ move.l a1,d0
++ move.b d1,(a0)+
++ cmp.b #0, d1
++ jne .L6
++ * to
++ move.l d0,a1
++ .L6:
++ move.b (a1)+,d1
++ move.b d1,(a0)+
++ cmp.b #0, d1
++ jne .L6
++ *
++ */
++static int
++propagate_moves ()
++{
++ rtx_insn *insn, *next;
++ rtx_insn * current_label = 0;
++ int change_count = 0;
++ std
++ ::vector<rtx_insn *> reg_reg;
++
++ for (insn = get_insns (); insn; insn = next)
++ {
++ next = NEXT_INSN (insn);
++
++ if (DEBUG_INSN_P(insn))
++ continue;
++
++ if (LABEL_P(insn))
++ {
++ if (LABEL_NUSES(insn) == 1)
++ {
++ current_label = insn;
++ reg_reg.clear ();
++ }
++ else
++ current_label = 0;
++ }
++
++ if (current_label == 0)
++ continue;
++
++ if (NONJUMP_INSN_P(insn))
++ {
++ // check for set reg, reg
++ rtx set = single_set (insn);
++ if (set)
++ {
++ rtx src = SET_SRC(set);
++ rtx dst = SET_DEST(set);
++ if (REG_P(src) && REG_P(dst))
++ reg_reg.push_back (insn);
++ }
++ continue;
++ }
++
++ if (JUMP_P(insn))
++ {
++ if (JUMP_LABEL (insn) == current_label && reg_reg.size () > 1)
++ {
++ /* Search for reg/reg pairs. */
++ for (auto i = reg_reg.begin ();
++ i != reg_reg.end () && i + 1 != reg_reg.end ();)
++ {
++ bool inc = true;
++ for (auto j = i + 1; j != reg_reg.end ();)
++ {
++ rtx seti = single_set (*i);
++ rtx srci = SET_SRC(seti);
++ rtx dsti = SET_DEST(seti);
++ rtx setj = single_set (*j);
++ rtx srcj = SET_SRC(setj);
++ rtx dstj = SET_DEST(setj);
++
++ if (rtx_equal_p (srci, dstj) && rtx_equal_p (srcj, dsti))
++ {
++ /* Ensure correct usage. */
++ if (!reg_used_between_p (srci, current_label, *i)
++ && !reg_used_between_p (srci, *i, *j)
++ && !reg_used_between_p (srci, *j, insn)
++ && !reg_used_between_p (dsti, current_label, *i)
++ && !reg_used_between_p (dsti, *j, insn))
++ {
++ fprintf (stderr,
++ "condition met, moving regs %d, %d\n",
++ REGNO(srci), REGNO(dsti));
++
++ /* Move out of loop. */
++ remove_insn (*i);
++ if (PREV_INSN (current_label))
++ add_insn_after (*i, PREV_INSN (current_label),
++ 0);
++ else
++ add_insn_before (*i, current_label, 0);
++
++ remove_insn (*j);
++ add_insn_after (*j, insn, 0);
++
++ reg_reg.erase (j);
++ reg_reg.erase (i);
++ j = reg_reg.end ();
++ inc = false;
++
++ ++change_count;
++ }
++ }
++ if (inc)
++ ++j;
++ }
++ if (inc)
++ ++i;
++ }
++ }
++ current_label = 0;
++ }
++ }
++
++ return change_count;
++}
++
++/**
++ * Search for
++ *
++ * mov x,reg
++ * mov reg,x
++ * cmp #0, reg
++ * jxx
++ *
++ * patterns.
++ *
++ * Use a simple state machine to find the patterns.
++ */
++static void
++opt_strcpy ()
++{
++ rtx_insn *insn, *next;
++ rtx_insn * x2reg = 0;
++ rtx_insn * reg2x;
++ unsigned int regno;
++
++ for (insn = get_insns (); insn; insn = next)
++ {
++ rtx src;
++
++ next = NEXT_INSN (insn);
++
++ if (NONJUMP_INSN_P(insn))
++ {
++ rtx set = single_set (insn);
++ if (!set)
++ continue;
++
++ if (x2reg && reg2x)
++ {
++ src = SET_SRC(set);
++ if (GET_CODE(src) == COMPARE)
++ {
++ rtx dst = XEXP(src, 0);
++ src = XEXP(src, 1);
++
++ if (CONST_INT_P(src) && INTVAL(src) == 0
++ && find_reg_note (insn, REG_DEAD, dst))
++ {
++ /* now check via NOTICE_UPDATE_CC*/
++ NOTICE_UPDATE_CC (PATTERN (reg2x), reg2x);
++ if (cc_status.flags == 0
++ && rtx_equal_p (dst, cc_status.value2))
++ {
++ int num_clobbers_to_add = 0;
++ int insn_code_number;
++
++ SET_SRC(single_set(reg2x)) = SET_SRC(
++ single_set (x2reg));
++ insn_code_number = recog (PATTERN (reg2x), reg2x,
++ &num_clobbers_to_add);
++
++ if (insn_code_number < 0)
++ {
++ /* restore register. */
++ SET_SRC(single_set(reg2x)) = SET_DEST(
++ single_set (x2reg));
++ }
++ else
++ {
++
++ rtx link;
++
++ fprintf (
++ stderr,
++ "condition met, removing compare and joining insns - omit reg %d\n",
++ REGNO(dst));
++
++ for (link = REG_NOTES(x2reg); link;
++ link = XEXP(link, 1))
++ if (REG_NOTE_KIND (link) != REG_LABEL_OPERAND)
++ {
++ if (GET_CODE (link) == EXPR_LIST)
++ add_reg_note (
++ reg2x, REG_NOTE_KIND(link),
++ copy_insn_1 (XEXP(link, 0)));
++ else
++ add_shallow_copy_of_reg_note (reg2x,
++ link);
++ }
++
++ SET_INSN_DELETED(x2reg);
++ SET_INSN_DELETED(insn);
++
++ df_insn_rescan (reg2x);
++
++ }
++ }
++ }
++ x2reg = 0;
++ continue;
++ }
++ reg2x = 0;
++ }
++
++ /* check for reg2x first, maybe fallback to x2reg. */
++ if (x2reg && reg2x == 0)
++ {
++ if (REG_P(SET_SRC(set)) && REGNO(SET_SRC(set)) == regno)
++ {
++ reg2x = insn;
++ continue;
++ }
++ x2reg = 0;
++ }
++
++ /* check for a match for x2reg. */
++ if (x2reg == 0)
++ {
++ if (REG_P(SET_DEST(set)))
++ {
++ x2reg = insn;
++ reg2x = 0;
++ regno = REGNO(SET_DEST(set));
++ }
++ }
++ }
++ }
++}
++
++/* Main entry point to the pass. */
++
++static unsigned int
++execute_bbb_optimizations (void)
++{
++ df_set_flags (DF_LR_RUN_DCE + DF_DEFER_INSN_RESCAN);
++ df_note_add_problem ();
++ df_analyze ();
++
++// dump_insns ("bbb 0");
++
++ propagate_moves ();
++
++ opt_strcpy ();
++
++ dump_insns ("bbb 1");
++
++ return 0;
++}
++
++namespace
++ {
++
++ const pass_data pass_data_bbb_optimizations =
++ {
++ RTL_PASS, /* type */
++ "bbb", /* name */
++ OPTGROUP_NONE, /* optinfo_flags */
++ TV_NONE, /* tv_id */
++ 0, /* properties_required */
++ 0, /* properties_provided */
++ 0, /* properties_destroyed */
++ 0, /* todo_flags_start */
++ ( TODO_df_finish | TODO_df_verify ), /* todo_flags_finish */
++ };
++
++ class pass_bbb_optimizations : public rtl_opt_pass
++ {
++ public:
++ pass_bbb_optimizations (gcc::context *ctxt)
++ : rtl_opt_pass (pass_data_bbb_optimizations, ctxt)
++ {}
++
++ /* opt_pass methods: */
++ virtual bool gate (function *)
++ {
++ return true;
++ }
++
++ virtual unsigned int execute (function *)
++ {
++ return execute_bbb_optimizations ();
++ }
++
++ }; // class pass_bbb_optimizations
++
++ } // anon namespace
++
++rtl_opt_pass *
++make_pass_bbb_optimizations (gcc::context *ctxt)
++ {
++ return new pass_bbb_optimizations (ctxt);
++ }
+diff --git a/gcc/passes.c b/gcc/passes.c
+index e89618111245..321adbc61e2d 100644
+--- gcc/passes.c
++++ gcc/passes.c
+@@ -2269,6 +2269,31 @@ override_gate_status (opt_pass *pass, tree func, bool gate_status)
+ }
+
+
++void dump_insns(char const * name)
++{
++ rtx_insn *insn, *next;
++ fprintf(stderr, "====================================\npass: %s\n", name);
++ for (insn = get_insns(); insn; insn = next)
++ {
++ next = NEXT_INSN(insn);
++ debug_rtx(insn);
++#if 0
++ if (NONJUMP_INSN_P (insn))
++ {
++ rtx x, y, set= single_set (insn);
++ if (!set)
++ continue;
++ x = y = SET_SRC(set);
++
++ while (GET_CODE(y) == CONST || GET_CODE(y) == PLUS)
++ y = XEXP(y, 0);
++ if (x != y && REG_P(y) && REGNO(y) == PIC_REG)
++ debug_rtx(insn);
++ }
++#endif
++ }
++}
++
+ /* Execute PASS. */
+
+ bool
+@@ -2278,6 +2303,8 @@ execute_one_pass (opt_pass *pass)
+
+ bool gate_status;
+
++// dump_insns(pass->name);
++
+ /* IPA passes are executed on whole program, so cfun should be NULL.
+ Other passes need function context set. */
+ if (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS)
+diff --git a/gcc/passes.def b/gcc/passes.def
+index ec796082ae7f..45ff86c383e4 100644
+--- gcc/passes.def
++++ gcc/passes.def
+@@ -446,6 +446,7 @@ along with GCC; see the file COPYING3. If not see
+ NEXT_PASS (pass_split_after_reload);
+ NEXT_PASS (pass_ree);
+ NEXT_PASS (pass_compare_elim_after_reload);
++ NEXT_PASS (pass_bbb_optimizations);
+ NEXT_PASS (pass_branch_target_load_optimize1);
+ NEXT_PASS (pass_jump2);
+ NEXT_PASS (pass_duplicate_computed_gotos);
+diff --git a/gcc/regrename.c b/gcc/regrename.c
+old mode 100644
+new mode 100755
+index 2dd96db5b87f..4ba825e8d8e8
+--- gcc/regrename.c
++++ gcc/regrename.c
+@@ -358,6 +358,7 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class,
+ enum reg_class preferred_class;
+ int best_new_reg = old_reg;
+ int new_reg;
++ int hit = 0;
+
+ /* Further narrow the set of registers we can use for renaming.
+ If the chain needs a call-saved register, mark the call-used
+@@ -404,9 +405,11 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class,
+ don't belong to PREFERRED_CLASS to registers that do, even
+ though the latters were used not very long ago.
+ Also use a register if no best_new_reg was found till now */
+- if ((tick[best_new_reg] > tick[new_reg]
+- || (old_reg == best_new_reg && new_reg < old_reg)))
+- best_new_reg = new_reg;
++ if (new_reg < old_reg || !hit)
++ {
++ hit = 1;
++ best_new_reg = new_reg;
++ }
+ }
+ return best_new_reg;
+ }
+diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
+index 5f5055d3a6c1..b3f66ad529b9 100644
+--- gcc/tree-pass.h
++++ gcc/tree-pass.h
+@@ -590,6 +590,7 @@ extern rtl_opt_pass *make_pass_branch_target_load_optimize2 (gcc::context
+ *ctxt);
+ extern rtl_opt_pass *make_pass_leaf_regs (gcc::context *ctxt);
+ extern rtl_opt_pass *make_pass_split_before_sched2 (gcc::context *ctxt);
++extern rtl_opt_pass *make_pass_bbb_optimizations (gcc::context *ctxt);
+ extern rtl_opt_pass *make_pass_compare_elim_after_reload (gcc::context *ctxt);
+ extern rtl_opt_pass *make_pass_sched2 (gcc::context *ctxt);
+ extern rtl_opt_pass *make_pass_stack_regs (gcc::context *ctxt);
+
+From eb051946c1a720575b80bcd5cf8038710f1c27c1 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 31 Mar 2017 11:19:56 +0200
+Subject: [PATCH 050/303] @B compiles again with other targets
+
+---
+ gcc/bbb-opts.c | 205 ++++++++++++++++++++++++++++++++++-----------------------
+ gcc/except.c | 1 +
+ 2 files changed, 124 insertions(+), 82 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index ff447c9e335e..aeec7a8b4e6a 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -107,11 +107,10 @@ dump_insns (char const * name);
+ static int
+ propagate_moves ()
+ {
++ int change_count = 0;
+ rtx_insn *insn, *next;
+ rtx_insn * current_label = 0;
+- int change_count = 0;
+- std
+- ::vector<rtx_insn *> reg_reg;
++ std::vector<rtx_insn *> reg_reg;
+
+ for (insn = get_insns (); insn; insn = next)
+ {
+@@ -153,11 +152,11 @@ propagate_moves ()
+ if (JUMP_LABEL (insn) == current_label && reg_reg.size () > 1)
+ {
+ /* Search for reg/reg pairs. */
+- for (auto i = reg_reg.begin ();
++ for (std::vector<rtx_insn *>::iterator i = reg_reg.begin ();
+ i != reg_reg.end () && i + 1 != reg_reg.end ();)
+ {
+ bool inc = true;
+- for (auto j = i + 1; j != reg_reg.end ();)
++ for (std::vector<rtx_insn *>::iterator j = i + 1; j != reg_reg.end ();)
+ {
+ rtx seti = single_set (*i);
+ rtx srci = SET_SRC(seti);
+@@ -208,7 +207,6 @@ propagate_moves ()
+ current_label = 0;
+ }
+ }
+-
+ return change_count;
+ }
+
+@@ -224,9 +222,11 @@ propagate_moves ()
+ *
+ * Use a simple state machine to find the patterns.
+ */
+-static void
++static int
+ opt_strcpy ()
+ {
++ int change_count = 0;
++#if HAVE_cc0
+ rtx_insn *insn, *next;
+ rtx_insn * x2reg = 0;
+ rtx_insn * reg2x;
+@@ -234,106 +234,145 @@ opt_strcpy ()
+
+ for (insn = get_insns (); insn; insn = next)
+ {
+- rtx src;
+-
+ next = NEXT_INSN (insn);
+
+- if (NONJUMP_INSN_P(insn))
+- {
+- rtx set = single_set (insn);
+- if (!set)
+- continue;
++ if (!NONJUMP_INSN_P(insn))
++ continue;
++
++ rtx set = single_set (insn);
++ if (!set)
++ continue;
+
+- if (x2reg && reg2x)
++ if (x2reg && reg2x)
++ {
++ rtx src = SET_SRC(set);
++ if (GET_CODE(src) == COMPARE)
+ {
+- src = SET_SRC(set);
+- if (GET_CODE(src) == COMPARE)
+- {
+- rtx dst = XEXP(src, 0);
+- src = XEXP(src, 1);
++ rtx dst = XEXP(src, 0);
++ src = XEXP(src, 1);
+
+- if (CONST_INT_P(src) && INTVAL(src) == 0
+- && find_reg_note (insn, REG_DEAD, dst))
++ if (CONST_INT_P(src) && INTVAL(src) == 0
++ && find_reg_note (insn, REG_DEAD, dst))
++ {
++ /* now check via NOTICE_UPDATE_CC*/
++ NOTICE_UPDATE_CC (PATTERN (reg2x), reg2x);
++ if (cc_status.flags == 0
++ && rtx_equal_p (dst, cc_status.value2))
+ {
+- /* now check via NOTICE_UPDATE_CC*/
+- NOTICE_UPDATE_CC (PATTERN (reg2x), reg2x);
+- if (cc_status.flags == 0
+- && rtx_equal_p (dst, cc_status.value2))
+- {
+- int num_clobbers_to_add = 0;
+- int insn_code_number;
++ int num_clobbers_to_add = 0;
++ int insn_code_number;
+
+- SET_SRC(single_set(reg2x)) = SET_SRC(
+- single_set (x2reg));
+- insn_code_number = recog (PATTERN (reg2x), reg2x,
+- &num_clobbers_to_add);
++ SET_SRC(single_set(reg2x)) = SET_SRC(single_set (x2reg));
++ insn_code_number = recog (PATTERN (reg2x), reg2x,
++ &num_clobbers_to_add);
+
+- if (insn_code_number < 0)
+- {
+- /* restore register. */
+- SET_SRC(single_set(reg2x)) = SET_DEST(
+- single_set (x2reg));
+- }
+- else
+- {
++ if (insn_code_number < 0)
++ {
++ /* restore register. */
++ SET_SRC(single_set(reg2x)) = SET_DEST(
++ single_set (x2reg));
++ }
++ else
++ {
+
+- rtx link;
++ rtx link;
+
+- fprintf (
+- stderr,
+- "condition met, removing compare and joining insns - omit reg %d\n",
+- REGNO(dst));
++ fprintf (
++ stderr,
++ "condition met, removing compare and joining insns - omit reg %d\n",
++ REGNO(dst));
+
+- for (link = REG_NOTES(x2reg); link;
+- link = XEXP(link, 1))
+- if (REG_NOTE_KIND (link) != REG_LABEL_OPERAND)
+- {
+- if (GET_CODE (link) == EXPR_LIST)
+- add_reg_note (
+- reg2x, REG_NOTE_KIND(link),
+- copy_insn_1 (XEXP(link, 0)));
+- else
+- add_shallow_copy_of_reg_note (reg2x,
+- link);
+- }
++ for (link = REG_NOTES(x2reg); link;
++ link = XEXP(link, 1))
++ if (REG_NOTE_KIND (link) != REG_LABEL_OPERAND)
++ {
++ if (GET_CODE (link) == EXPR_LIST)
++ add_reg_note (reg2x, REG_NOTE_KIND(link),
++ copy_insn_1 (XEXP(link, 0)));
++ else
++ add_shallow_copy_of_reg_note (reg2x, link);
++ }
+
+- SET_INSN_DELETED(x2reg);
+- SET_INSN_DELETED(insn);
++ SET_INSN_DELETED(x2reg);
++ SET_INSN_DELETED(insn);
+
+- df_insn_rescan (reg2x);
++ df_insn_rescan (reg2x);
+
+- }
++ ++change_count;
+ }
+ }
+- x2reg = 0;
+- continue;
+ }
+- reg2x = 0;
++ x2reg = 0;
++ continue;
+ }
++ reg2x = 0;
++ }
+
+- /* check for reg2x first, maybe fallback to x2reg. */
+- if (x2reg && reg2x == 0)
++ /* check for reg2x first, maybe fallback to x2reg. */
++ if (x2reg && reg2x == 0)
++ {
++ if (REG_P(SET_SRC(set)) && REGNO(SET_SRC(set)) == regno)
+ {
+- if (REG_P(SET_SRC(set)) && REGNO(SET_SRC(set)) == regno)
+- {
+- reg2x = insn;
+- continue;
+- }
+- x2reg = 0;
++ reg2x = insn;
++ continue;
+ }
++ x2reg = 0;
++ }
+
+- /* check for a match for x2reg. */
+- if (x2reg == 0)
++ /* check for a match for x2reg. */
++ if (x2reg == 0)
++ {
++ if (REG_P(SET_DEST(set)))
+ {
+- if (REG_P(SET_DEST(set)))
+- {
+- x2reg = insn;
+- reg2x = 0;
+- regno = REGNO(SET_DEST(set));
+- }
++ x2reg = insn;
++ reg2x = 0;
++ regno = REGNO(SET_DEST(set));
+ }
+ }
+ }
++#endif
++ return change_count;
++}
++
++/*
++ * Convert loops using a counting reg as offset with an address reg
++ * into a loop with auto inc address regs.
++ */
++static int
++offset_2_autoinc (void)
++{
++ rtx_insn *insn, *next;
++ rtx_insn * reg_const = 0;
++ int change_count = 0;
++
++ for (insn = get_insns (); insn; insn = next)
++ {
++ next = NEXT_INSN (insn);
++
++ if (!next || !LABEL_P(next) || LABEL_NUSES(next) != 1)
++ continue;
++
++ if (!NONJUMP_INSN_P(insn))
++ continue;
++
++ rtx set = single_set (insn);
++ if (!set)
++ continue;
++
++ rtx reg = SET_DEST(set);
++ if (!REG_P(reg))
++ continue;
++
++ rtx val = SET_SRC(set);
++
++
++// fprintf(stderr, "possible start for offset_2_autoinc\n");
++// debug_rtx(insn);
++// debug_rtx(next);
++
++ }
++
++ return change_count;
+ }
+
+ /* Main entry point to the pass. */
+@@ -349,9 +388,11 @@ execute_bbb_optimizations (void)
+
+ propagate_moves ();
+
++ offset_2_autoinc ();
++
+ opt_strcpy ();
+
+- dump_insns ("bbb 1");
++// dump_insns ("bbb 1");
+
+ return 0;
+ }
+diff --git a/gcc/except.c b/gcc/except.c
+index 156d7b76d249..194478f8454c 100644
+--- gcc/except.c
++++ gcc/except.c
+@@ -142,6 +142,7 @@ along with GCC; see the file COPYING3. If not see
+ #include "cfgloop.h"
+ #include "builtins.h"
+ #include "tree-hash-traits.h"
++#include "target-def.h"
+
+ static GTY(()) int call_site_base;
+
+
+From 73b869461936fd68a37b9edc8f0e4eba48d5c440 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 5 Apr 2017 16:03:47 +0200
+Subject: [PATCH 051/303] @R use a5 instead of fp
+
+---
+ gcc/config/m68k/amigaos.h | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h
+index 7259611edc9e..ce47723e962f 100644
+--- gcc/config/m68k/amigaos.h
++++ gcc/config/m68k/amigaos.h
+@@ -153,11 +153,7 @@ amiga_named_section (const char *name, unsigned int flags, tree decl);
+ #define FRAME_POINTER_REGNUM 13
+
+ #undef M68K_REGNAME
+-#define M68K_REGNAME(r) ( \
+- ( ((r) == FRAME_POINTER_REGNUM) \
+- && frame_pointer_needed) ? \
+- M68K_FP_REG_NAME : reg_names[(r)])
+-
++#define M68K_REGNAME(r) (reg_names[(r)])
+
+ /* The AmigaOS ABI does not define how structures should be returned, so,
+ contrary to 'm68k.h', we prefer a multithread-safe solution. */
+
+From 626d238b27f86a4369aeb13ad11153accd414f90 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 5 Apr 2017 16:06:55 +0200
+Subject: [PATCH 052/303] @R make MEM_P more expensive than REG_P
+
+---
+ gcc/config/m68k/m68k.c | 30 ++++++++++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+
+diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
+index d60371a92bc6..6c0d9211598d 100644
+--- gcc/config/m68k/m68k.c
++++ gcc/config/m68k/m68k.c
+@@ -2928,6 +2928,17 @@ m68k_rtx_costs (rtx x, machine_mode mode, int outer_code,
+ *total = COSTS_N_INSNS (TARGET_COLDFIRE ? 2 : 3);
+ return true;
+ }
++ /* reg + value */
++// if (mode == SImode
++// && REG_P(XEXP(x, 0))) {
++// if (m68k_rtx_costs(XEXP(x, 1), mode, PLUS, 1, total, speed))
++// {
++// if (REGNO_REG_CLASS(REGNO(XEXP(x, 0))) == ADDR_REGS)
++// *total += 4;
++// return true;
++// }
++// }
++
+ return false;
+
+ case ASHIFT:
+@@ -2996,6 +3007,25 @@ m68k_rtx_costs (rtx x, machine_mode mode, int outer_code,
+ *total = 0;
+ return false;
+
++ case MEM:
++ {
++ /* simple but not exact */
++ rtx y = XEXP(x, 0);
++ int yc = GET_CODE(y);
++ if (yc == REG || yc == PRE_INC || yc == POST_INC || yc == POST_DEC)
++ *total += 4;
++ else
++ if (yc == PRE_DEC)
++ *total += 6;
++ else
++ *total += 8;
++
++ if (mode != QImode && mode != QImode)
++ *total += 4;
++
++ return true;
++ }
++
+ default:
+ return false;
+ }
+
+From 9c9c8b4c31a9ed000a27ff22245ad21b7ad21e67 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 5 Apr 2017 16:08:30 +0200
+Subject: [PATCH 053/303] @R added reg life analysis to own optimizer
+
+---
+ gcc/bbb-opts.c | 793 ++++++++++++++++++++++++++++++++++++++++++++++++---------
+ gcc/passes.def | 1 +
+ 2 files changed, 672 insertions(+), 122 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index aeec7a8b4e6a..7fd01139d0f3 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -25,11 +25,16 @@
+ * #1 propagate_moves
+ * check if a->b->a can be moved out of a loop.
+ *
+- * #2 strcpy
++ * #2 strcpy_opt
+ * move a,reg
+ * move reg,b
+ * cmp #0,reg
+- * jne/jeq
++ * jcc
++ *
++ * ->
++ * move a,b
++ * jcc
++ *
+ */
+
+ #include "config.h"
+@@ -49,8 +54,285 @@
+ #include <vector>
+ #include <map>
+
+-extern void
+-dump_insns (char const * name);
++/* enough for m68k. */
++typedef unsigned insn_info; //[(FIRST_PSEUDO_REGISTER + sizeof(unsigned) * 8 - 1) / (sizeof(unsigned) * 8)];
++
++static inline void
++resetii (unsigned & ii)
++{
++ ii = 0;
++}
++
++static inline void
++setii (unsigned regno, unsigned & ii)
++{
++ ii |= 1 << regno;
++}
++
++static inline void
++clearii (unsigned regno, unsigned & ii)
++{
++ ii &= ~(1 << regno);
++}
++
++static inline bool
++getii (unsigned regno, unsigned & ii)
++{
++ return ii & (1 << regno) ? true : false;
++}
++
++/* scan rtx for registers. */
++static void
++scanii (rtx x, unsigned & ii)
++{
++ if (REG_P(x))
++ {
++ setii (REGNO(x), ii);
++ return;
++ }
++
++ RTX_CODE code = GET_CODE(x);
++ const char *fmt = GET_RTX_FORMAT(code);
++ for (int i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
++ {
++ if (fmt[i] == 'e')
++ scanii (XEXP(x, i), ii);
++ else if (fmt[i] == 'E')
++ for (int j = XVECLEN (x, i) - 1; j >= 0; j--)
++ scanii (XVECEXP(x, i, j), ii);
++ }
++}
++
++static std::vector<rtx_insn *> insns;
++static std::vector<rtx_insn *> jumps;
++static std::map<rtx_insn *, unsigned> insn2index;
++static std::vector<insn_info> infos;
++
++static void
++clear (void)
++{
++ insns.clear ();
++ jumps.clear ();
++ insn2index.clear ();
++ infos.clear ();
++}
++
++static void
++dump_costs (void)
++{
++ rtx d0 = gen_raw_REG (SImode, 0);
++ rtx d0b = gen_raw_REG (QImode, 0);
++ rtx d1 = gen_raw_REG (SImode, 1);
++ rtx d1b = gen_raw_REG (QImode, 1);
++ rtx a0 = gen_raw_REG (SImode, 8);
++ rtx a1 = gen_raw_REG (SImode, 9);
++
++ struct ICO
++ {
++ char const * name;
++ rtx set;
++ } data[] =
++ {
++ { "move d0,(a0)", gen_rtx_SET(gen_rtx_MEM (SImode, a0), d0) },
++ { "move a0,d0", gen_rtx_SET(d0, a0) },
++ { "move (a0),d0", gen_rtx_SET(d0, gen_rtx_MEM (SImode, a0)) },
++ { "move d0,(a0)", gen_rtx_SET(gen_rtx_MEM (SImode, a0), d0) },
++ { "move d1,(a1)+", gen_rtx_SET(d1, gen_rtx_MEM (SImode, gen_rtx_POST_INC (SImode, a1))) },
++ { "move (a0),(a1)", gen_rtx_SET(gen_rtx_MEM (SImode, a1), gen_rtx_MEM (SImode, a0)) },
++ { 0, 0 } }, *p;
++
++ for (p = data; p->name; ++p)
++ {
++ int cost = insn_rtx_cost (p->set, true);
++ fprintf (stderr, "%s: %d\n", p->name, cost);
++ }
++}
++
++
++static void
++dump_insns (char const * name)
++{
++ rtx_insn *insn, *next;
++ fprintf(stderr, "====================================: %s\n", name);
++ for (unsigned i = 0; i < insns.size(); ++i)
++ {
++ insn_info & ii = infos[i];
++
++ for (int j = 0; j < 8; ++j)
++ if (getii(j, ii))
++ fprintf(stderr, "d%d ", j);
++
++ for (int j = 8; j < 16; ++j)
++ if (getii(j, ii))
++ fprintf(stderr, "a%d ", j-8);
++
++ fprintf(stderr, "\t");
++ debug_rtx(insns[i]);
++ }
++}
++
++
++/*
++ * Create a filtered view of insns - keep only those to work with.
++ */
++static void
++filter_insns ()
++{
++ rtx_insn *insn, *next;
++ clear ();
++
++ df_insn_rescan_all ();
++
++ /* create a vector with relevant insn. */
++ for (insn = get_insns (); insn; insn = next)
++ {
++ next = NEXT_INSN (insn);
++
++ if (NONJUMP_INSN_P (insn) || LABEL_P(insn) || JUMP_P(insn) || CALL_P(insn))
++ {
++ // debug_rtx (insn);
++ if (JUMP_P(insn))
++ jumps.push_back(insn);
++
++ insn2index.insert (std::make_pair (insn, insns.size ()));
++ insns.push_back (insn);
++ }
++ }
++
++ /* prepare insn_info */
++ insn_info ii;
++ resetii (ii);
++ for (unsigned i = 0; i < insns.size (); ++i)
++ {
++ infos.push_back (ii);
++ }
++
++ /* own analyze life */
++ std::vector<std::pair<unsigned, insn_info>> todo;
++ todo.push_back (std::make_pair (insns.size () - 1, ii));
++
++ int pass = 0;
++ while (!todo.empty ())
++ {
++ std::pair<unsigned, insn_info> p = *todo.rbegin ();
++ todo.pop_back ();
++
++ insn_info ii = p.second;
++
++ for (int pos = p.first; pos >= 0; --pos)
++ {
++ rtx_insn * insn = insns[pos];
++
++ if (pass && ii == infos[pos])
++ break;
++
++ ii |= infos[pos];
++
++ if (LABEL_P(insn))
++ {
++ /* work on all jumps referring to that label. */
++ for (std::vector<rtx_insn *>::iterator i = jumps.begin (); i != jumps.end (); ++i)
++ {
++ if (JUMP_LABEL(*i) == insn)
++ {
++ std::map<rtx_insn *, unsigned>::iterator j = insn2index.find (*i);
++ if (j != insn2index.end())
++ todo.push_back (std::make_pair (j->second, ii));
++ }
++ }
++ continue;
++ }
++
++ rtx set = single_set (insn);
++ if (set == 0)
++ {
++ if (JUMP_P(insn)) {
++ resetii(ii);
++ setii(0, ii);
++ infos[pos] = ii;
++ continue;
++ }
++ fprintf(stderr, "##### ");
++ debug_rtx(insn);
++ continue;
++ }
++
++ rtx src = SET_SRC(set);
++ rtx dst = SET_DEST(set);
++
++ debug_rtx(insn);
++
++ if (CALL_P(insn))
++ {
++ /* a call sets d0 and kills d1,a0,a1. */
++ if (getii (1, ii))
++ fprintf (stderr, "d1 used after call\n");
++ if (getii (8, ii))
++ fprintf (stderr, "a0 used after call\n");
++ if (getii (9, ii))
++ fprintf (stderr, "a1 used after call\n");
++
++ resetii (ii);
++ // use regs depending on flag mregparm
++ for (int i = 0; i < amigaos_regparm; ++i)
++ {
++ setii (i, ii);
++ setii (i + 8, ii);
++ }
++
++ // check for reg use
++ if (REG_P(src))
++ setii (REGNO(src), ii);
++
++ infos[pos] = ii;
++ continue;
++ }
++
++ if (JUMP_P(insn))
++ {
++ if (ANY_RETURN_P(src))
++ {
++ resetii (ii);
++ setii (0, ii);
++ }
++ else
++ {
++ ii |= infos[pos];
++
++ // check for reg use
++ if (REG_P(src))
++ setii (REGNO(src), ii);
++
++ }
++ infos[pos] = ii;
++ continue;
++ }
++
++ // scan insn for regs
++ // a def stop propagation
++ // a use starts propagation
++ // also add use to current ii
++ insn_info use;
++ resetii (use);
++
++ insn_info def;
++ resetii (def);
++
++ scanii (src, use);
++ if (REG_P(dst))
++ setii (REGNO(dst), def);
++ else
++ scanii (dst, use);
++
++ infos[pos] = use | ii;
++
++ ii &= ~def;
++ ii |= use;
++ }
++ ++pass;
++ }
++
++}
+
+ /*
+ * #1 propagate a->b->a moves out of a loop.
+@@ -102,29 +384,34 @@ dump_insns (char const * name);
+ move.b d1,(a0)+
+ cmp.b #0, d1
+ jne .L6
++
+ *
++ * Also allow exit jumps, if the modification of the reg is const
++ * and insert a correction after the exit label.
++ * The label must only be reachable by the exit jump.
+ */
+-static int
++static unsigned
+ propagate_moves ()
+ {
+- int change_count = 0;
+- rtx_insn *insn, *next;
++ unsigned change_count = 0;
+ rtx_insn * current_label = 0;
+- std::vector<rtx_insn *> reg_reg;
++ unsigned current_label_index;
++ std::vector<unsigned> reg_reg;
++ std::vector<rtx_insn *> jump_out;
+
+- for (insn = get_insns (); insn; insn = next)
++ /* start at 1 since there must be an insn before the label. */
++ for (unsigned index = 1; index < insns.size (); ++index)
+ {
+- next = NEXT_INSN (insn);
+-
+- if (DEBUG_INSN_P(insn))
+- continue;
++ rtx_insn * insn = insns[index];
+
+ if (LABEL_P(insn))
+ {
+ if (LABEL_NUSES(insn) == 1)
+ {
+ current_label = insn;
++ current_label_index = index;
+ reg_reg.clear ();
++ jump_out.clear ();
+ }
+ else
+ current_label = 0;
+@@ -142,59 +429,180 @@ propagate_moves ()
+ rtx src = SET_SRC(set);
+ rtx dst = SET_DEST(set);
+ if (REG_P(src) && REG_P(dst))
+- reg_reg.push_back (insn);
++ reg_reg.push_back (index);
+ }
++ else
++ current_label = 0;
++
+ continue;
+ }
+
+ if (JUMP_P(insn))
+ {
+- if (JUMP_LABEL (insn) == current_label && reg_reg.size () > 1)
++ rtx_insn * label = (rtx_insn *) JUMP_LABEL(insn);
++ if (label != current_label)
++ {
++ /* collect the labels for a later check if a fixup is possible. */
++ if (LABEL_NUSES(label) == 1 && BARRIER_P(PREV_INSN (label)))
++ jump_out.push_back (label);
++ else
++ current_label = 0;
++ continue;
++ }
++
++ if (reg_reg.size () > 1)
+ {
+ /* Search for reg/reg pairs. */
+- for (std::vector<rtx_insn *>::iterator i = reg_reg.begin ();
+- i != reg_reg.end () && i + 1 != reg_reg.end ();)
++ for (std::vector<unsigned>::iterator i = reg_reg.begin (); i != reg_reg.end () && i + 1 != reg_reg.end ();
++ )
+ {
+ bool inc = true;
+- for (std::vector<rtx_insn *>::iterator j = i + 1; j != reg_reg.end ();)
++ for (std::vector<unsigned>::iterator j = i + 1; j != reg_reg.end ();)
+ {
+- rtx seti = single_set (*i);
++ rtx_insn * ii = insns[*i];
++ rtx seti = single_set (ii);
+ rtx srci = SET_SRC(seti);
+ rtx dsti = SET_DEST(seti);
+- rtx setj = single_set (*j);
++ rtx_insn * jj = insns[*j];
++ rtx setj = single_set (jj);
+ rtx srcj = SET_SRC(setj);
+ rtx dstj = SET_DEST(setj);
+
+ if (rtx_equal_p (srci, dstj) && rtx_equal_p (srcj, dsti))
+ {
+ /* Ensure correct usage. */
+- if (!reg_used_between_p (srci, current_label, *i)
+- && !reg_used_between_p (srci, *i, *j)
+- && !reg_used_between_p (srci, *j, insn)
+- && !reg_used_between_p (dsti, current_label, *i)
+- && !reg_used_between_p (dsti, *j, insn))
++ if (!reg_used_between_p (srci, current_label, ii) && !reg_used_between_p (srci, ii, jj)
++ && !reg_used_between_p (srci, jj, insn) && !reg_used_between_p (dsti, current_label, ii)
++ && !reg_used_between_p (dsti, jj, insn))
+ {
+- fprintf (stderr,
+- "condition met, moving regs %d, %d\n",
+- REGNO(srci), REGNO(dsti));
+-
+- /* Move out of loop. */
+- remove_insn (*i);
+- if (PREV_INSN (current_label))
+- add_insn_after (*i, PREV_INSN (current_label),
+- 0);
+- else
+- add_insn_before (*i, current_label, 0);
+-
+- remove_insn (*j);
+- add_insn_after (*j, insn, 0);
+-
+- reg_reg.erase (j);
+- reg_reg.erase (i);
+- j = reg_reg.end ();
+- inc = false;
+-
+- ++change_count;
++ std::vector<int> fixups;
++
++ /* if there are jumps out of the loop,
++ * check if the modification occurs before the jump,
++ * and if, that it's a plus const.
++ */
++ if (jump_out.size ())
++ {
++ std::vector<rtx_insn *>::iterator label_iter = jump_out.begin ();
++ int fixup = 0;
++ fprintf (stderr, "need %d jump out fixups\n", jump_out.size ());
++
++ for (unsigned k = *i + 1; k != *j; ++k)
++ {
++ rtx_insn * check = insns[k];
++ if (JUMP_P(check))
++ {
++ fixups.push_back (fixup);
++ if (++label_iter == jump_out.end ())
++ break;
++ continue;
++ }
++
++ if (reg_overlap_mentioned_p (dsti, PATTERN (check)))
++ {
++ /* right now only support auto_incs. */
++ rtx set = single_set (check);
++ rtx src = SET_SRC(set);
++ rtx dst = SET_DEST(set);
++
++ if (reg_overlap_mentioned_p (dsti, dst))
++ {
++ if (REG_P(dst))
++ break;
++ if (!MEM_P(dst))
++ break;
++
++ rtx x = XEXP(dst, 0);
++ if (GET_CODE(x) == REG)
++ fixup += 0; // direct use
++ else if (GET_CODE(x) == PRE_INC ||
++ GET_CODE(x) == POST_INC)
++ fixup -= GET_MODE_SIZE(GET_MODE(dst));
++ else if (GET_CODE(dst) == PRE_DEC ||
++ GET_CODE(dst) == POST_DEC)
++ fixup += GET_MODE_SIZE(GET_MODE(dst));
++ else
++ break;
++ }
++
++ if (reg_overlap_mentioned_p (dsti, src))
++ {
++ if (REG_P(src))
++ fixup += 0;
++ else
++ {
++ if (!MEM_P(src))
++ break;
++
++ rtx x = XEXP(src, 0);
++ if (GET_CODE(x) == REG)
++ fixup += 0; // direct use
++ else if (GET_CODE(x) == PRE_INC ||
++ GET_CODE(x) == POST_INC)
++ fixup -= GET_MODE_SIZE(GET_MODE(dst));
++ else if (GET_CODE(dst) == PRE_DEC ||
++ GET_CODE(dst) == POST_DEC)
++ fixup += GET_MODE_SIZE(GET_MODE(dst));
++ else
++ break;
++ }
++ }
++ }
++ }
++ }
++
++ /* got a fixup for all jump_outs? */
++ if (fixups.size () == jump_out.size ())
++ {
++ rtx_insn * before = insns[current_label_index - 1];
++ rtx_insn * after = insns[index + 1];
++ rtx bset = single_set (before);
++
++ fprintf (stderr, "condition met, moving regs %d, %d\n", REGNO(srci), REGNO(dsti));
++
++ /* Move in front of loop and mark as dead. */
++ remove_insn (ii);
++ add_insn_after (ii, before, 0);
++ add_reg_note (ii, REG_DEAD, srci);
++
++ /* Plus check if the reg was just loaded. */
++ if (bset)
++ {
++ rtx bdst = SET_DEST(bset);
++ if (REG_P(bdst) && REGNO(bdst) == REGNO(srci))
++ {
++ SET_DEST(bset) = dsti;
++ SET_INSN_DELETED(ii);
++ }
++ }
++
++ /* Move behind loop - into next BB. */
++ remove_insn (jj);
++ add_insn_before (jj, after, 0);
++
++ reg_reg.erase (j);
++ reg_reg.erase (i);
++ j = reg_reg.end ();
++ inc = false;
++
++ df_insn_rescan (ii);
++ df_insn_rescan (jj);
++
++ /* add fixes if there were jumps out of the loop. */
++ if (jump_out.size ())
++ {
++ fprintf (stderr, "fixing %d jump outs\n", jump_out.size ());
++
++ for (unsigned k = 0; k < jump_out.size (); ++k)
++ {
++ rtx neu = gen_rtx_SET(
++ dstj, gen_rtx_PLUS(Pmode, dsti, gen_rtx_CONST_INT(Pmode, fixups[k])));
++ rtx_insn * neui = emit_insn_after (neu, jump_out[k]);
++ df_insn_rescan (neui);
++ }
++ }
++ ++change_count;
++ }
+ }
+ }
+ if (inc)
+@@ -222,19 +630,18 @@ propagate_moves ()
+ *
+ * Use a simple state machine to find the patterns.
+ */
+-static int
++static unsigned
+ opt_strcpy ()
+ {
+- int change_count = 0;
++ unsigned change_count = 0;
+ #if HAVE_cc0
+- rtx_insn *insn, *next;
+ rtx_insn * x2reg = 0;
+ rtx_insn * reg2x;
+ unsigned int regno;
+
+- for (insn = get_insns (); insn; insn = next)
++ for (unsigned index = 0; index < insns.size (); ++index)
+ {
+- next = NEXT_INSN (insn);
++ rtx_insn * insn = insns[index];
+
+ if (!NONJUMP_INSN_P(insn))
+ continue;
+@@ -251,26 +658,22 @@ opt_strcpy ()
+ rtx dst = XEXP(src, 0);
+ src = XEXP(src, 1);
+
+- if (CONST_INT_P(src) && INTVAL(src) == 0
+- && find_reg_note (insn, REG_DEAD, dst))
++ if (CONST_INT_P(src) && INTVAL(src) == 0 && find_reg_note (insn, REG_DEAD, dst))
+ {
+ /* now check via NOTICE_UPDATE_CC*/
+- NOTICE_UPDATE_CC (PATTERN (reg2x), reg2x);
+- if (cc_status.flags == 0
+- && rtx_equal_p (dst, cc_status.value2))
++ NOTICE_UPDATE_CC(PATTERN (reg2x), reg2x);
++ if (cc_status.flags == 0 && rtx_equal_p (dst, cc_status.value2))
+ {
+ int num_clobbers_to_add = 0;
+ int insn_code_number;
+
+ SET_SRC(single_set(reg2x)) = SET_SRC(single_set (x2reg));
+- insn_code_number = recog (PATTERN (reg2x), reg2x,
+- &num_clobbers_to_add);
++ insn_code_number = recog (PATTERN (reg2x), reg2x, &num_clobbers_to_add);
+
+ if (insn_code_number < 0)
+ {
+ /* restore register. */
+- SET_SRC(single_set(reg2x)) = SET_DEST(
+- single_set (x2reg));
++ SET_SRC(single_set(reg2x)) = SET_DEST(single_set (x2reg));
+ }
+ else
+ {
+@@ -278,17 +681,14 @@ opt_strcpy ()
+ rtx link;
+
+ fprintf (
+- stderr,
+- "condition met, removing compare and joining insns - omit reg %d\n",
+- REGNO(dst));
++ stderr,
++ "condition met, removing compare and joining insns - omit reg %d\n", REGNO(dst));
+
+- for (link = REG_NOTES(x2reg); link;
+- link = XEXP(link, 1))
++ for (link = REG_NOTES(x2reg); link; link = XEXP(link, 1))
+ if (REG_NOTE_KIND (link) != REG_LABEL_OPERAND)
+ {
+ if (GET_CODE (link) == EXPR_LIST)
+- add_reg_note (reg2x, REG_NOTE_KIND(link),
+- copy_insn_1 (XEXP(link, 0)));
++ add_reg_note (reg2x, REG_NOTE_KIND(link), copy_insn_1 (XEXP(link, 0)));
+ else
+ add_shallow_copy_of_reg_note (reg2x, link);
+ }
+@@ -338,45 +738,165 @@ opt_strcpy ()
+ * Convert loops using a counting reg as offset with an address reg
+ * into a loop with auto inc address regs.
+ */
+-static int
++static unsigned
+ offset_2_autoinc (void)
+ {
+- rtx_insn *insn, *next;
++ unsigned change_count = 0;
++#if 0
+ rtx_insn * reg_const = 0;
+- int change_count = 0;
+
+- for (insn = get_insns (); insn; insn = next)
++ for (unsigned index = 0; index < insns.size (); ++index)
+ {
+- next = NEXT_INSN (insn);
++ rtx_insn * insn = insns[index];
+
+ if (!next || !LABEL_P(next) || LABEL_NUSES(next) != 1)
+- continue;
++ continue;
+
+ if (!NONJUMP_INSN_P(insn))
+- continue;
++ continue;
+
+ rtx set = single_set (insn);
+ if (!set)
+- continue;
++ continue;
+
+ rtx reg = SET_DEST(set);
+ if (!REG_P(reg))
+- continue;
++ continue;
+
+ rtx val = SET_SRC(set);
+
+-
+ // fprintf(stderr, "possible start for offset_2_autoinc\n");
+-// debug_rtx(insn);
+-// debug_rtx(next);
++// //debug_rtx(insn);
++// //debug_rtx(next);
+
+ }
+
++#endif
+ return change_count;
+ }
+
+-/* Main entry point to the pass. */
++/*
++ * convert
++ *
++ * set reg1, plus (reg2, const)
++ * set mem(reg2), y
++ *
++ * ->
++ * set reg1, reg2
++ * set mem(reg1+), y
++ *
++ * if size of postinc == const
++ *
++ (insn 33 32 35 4 (set (reg/v/f:SI 8 a0 [orig:47 s ] [47])
++ (plus:SI (reg/v/f:SI 9 a1 [orig:46 s ] [46])
++ (const_int 1 [0x1]))) sn.c:5 141 {*addsi3_internal}
++ (nil))
++ (insn 36 35 37 4 (set (mem:QI (reg/v/f:SI 9 a1 [orig:46 s ] [46]) [0 MEM[base: s_17, offset: 4294967295B]+0 S1 A8])
++ (mem:QI (post_inc:SI (reg/v/f:SI 10 a2 [orig:53 s2 ] [53])) [0 MEM[base: s2_19, offset: 4294967295B]+0 S1 A8])) sn.c:5 46 {*m68k.md:1083}
++ (expr_list:REG_INC (reg/v/f:SI 10 a2 [orig:53 s2 ] [53])
++ (nil)))
++ */
++static unsigned
++commute_add_move (void)
++{
++ unsigned change_count = 0;
++
++ for (unsigned index = 0; index + 1 < insns.size (); ++index)
++ {
++ rtx_insn * insn = insns[index];
++ rtx set = single_set (insn);
++ if (!set)
++ continue;
++
++ rtx reg1 = SET_DEST(set);
++ if (!REG_P(reg1))
++ continue;
++
++ rtx plus = SET_SRC(set);
++ if (GET_CODE(plus) != PLUS)
++ continue;
++
++ rtx reg2 = XEXP(plus, 0);
++ if (!REG_P(reg2))
++ continue;
++
++ rtx cnst = XEXP(plus, 1);
++ if (!CONST_INT_P(cnst))
++ continue;
++
++ rtx_insn * next = insns[index + 1];
++ rtx set2 = single_set (next);
++ if (!set2)
++ continue;
++
++ rtx dst = SET_DEST(set2);
++ if (!MEM_P(dst) || GET_MODE_SIZE(GET_MODE(dst)) != INTVAL(cnst))
++ continue;
++
++ rtx memreg = XEXP(dst, 0);
++ if (!REG_P(memreg) || REGNO(memreg) != REGNO(reg2))
++ continue;
+
++ int oldcost1 = insn_rtx_cost (set, true);
++ int oldcost2 = insn_rtx_cost (set2, true);
++
++ fprintf (stderr, "commute_add_move found, oldcost: %d = %d + %d\n", oldcost1 + oldcost2, oldcost1, oldcost2);
++
++ //debug_rtx (insn);
++ //debug_rtx (next);
++
++ rtx pinc = gen_rtx_POST_INC(GET_MODE(dst), reg1);
++ rtx newmem = replace_equiv_address_nv (dst, pinc);
++
++ if (validate_change (next, &SET_DEST(set2), newmem, 0))
++ {
++ SET_INSN_DELETED(insn);
++
++ insn = emit_insn_before (gen_movsi (reg1, reg2), next);
++
++ add_reg_note (next, REG_INC, reg1);
++
++ int newcost1 = insn_rtx_cost (set, true);
++ int newcost2 = insn_rtx_cost (set2, true);
++
++ fprintf (stderr, "commute_add_move found, newcost: %d = %d + %d\n", newcost1 + newcost2, newcost1, newcost2);
++
++ //debug_rtx (insn);
++ //debug_rtx (next);
++
++ df_insn_rescan (insn);
++ df_insn_rescan (next);
++
++ ++change_count;
++ }
++ }
++ return change_count;
++}
++
++static unsigned
++const_cmp_to_sub (void)
++{
++ unsigned change_count = 0;
++#if HAVE_cc0
++ for (unsigned index = 0; index + 1 < insns.size (); ++index)
++ {
++ rtx_insn * insn = insns[index];
++ rtx set = single_set (insn);
++ if (!set)
++ continue;
++
++ rtx dst = SET_DEST(set);
++ if (dst != cc0_rtx)
++ continue;
++
++ fprintf (stderr, "cc0:");
++ debug_rtx (insn);
++ }
++#endif
++ return change_count;
++}
++
++/* Main entry point to the pass. */
+ static unsigned int
+ execute_bbb_optimizations (void)
+ {
+@@ -385,58 +905,87 @@ execute_bbb_optimizations (void)
+ df_analyze ();
+
+ // dump_insns ("bbb 0");
++ filter_insns ();
++
++ for (;;)
++ {
++ int done = 1;
++ if (propagate_moves ())
++ done = 0, filter_insns ();
++
++ if (offset_2_autoinc ())
++ done = 0, filter_insns ();
+
+- propagate_moves ();
++ if (opt_strcpy ())
++ done = 0, filter_insns ();
+
+- offset_2_autoinc ();
++ if (commute_add_move ())
++ done = 0, filter_insns ();
+
+- opt_strcpy ();
++ if (const_cmp_to_sub ())
++ done = 0, filter_insns ();
+
+-// dump_insns ("bbb 1");
++ if (done)
++ break;
++ }
++
++ dump_insns ("bbb 1");
++ clear ();
++
++ dump_costs ();
+
+ return 0;
+ }
+
+ namespace
++{
++
++ const pass_data pass_data_bbb_optimizations =
++ { RTL_PASS, /* type */
++ "bbb", /* name */
++ OPTGROUP_NONE, /* optinfo_flags */
++ TV_NONE, /* tv_id */
++ 0, /* properties_required */
++ 0, /* properties_provided */
++ 0, /* properties_destroyed */
++ 0, /* todo_flags_start */
++ ( TODO_df_finish | TODO_df_verify), /* todo_flags_finish */
++ };
++
++ class pass_bbb_optimizations : public rtl_opt_pass
+ {
++ public:
++ pass_bbb_optimizations (gcc::context *ctxt) :
++ rtl_opt_pass (pass_data_bbb_optimizations, ctxt)
++ {
++ }
+
+- const pass_data pass_data_bbb_optimizations =
+- {
+- RTL_PASS, /* type */
+- "bbb", /* name */
+- OPTGROUP_NONE, /* optinfo_flags */
+- TV_NONE, /* tv_id */
+- 0, /* properties_required */
+- 0, /* properties_provided */
+- 0, /* properties_destroyed */
+- 0, /* todo_flags_start */
+- ( TODO_df_finish | TODO_df_verify ), /* todo_flags_finish */
+- };
+-
+- class pass_bbb_optimizations : public rtl_opt_pass
+- {
+- public:
+- pass_bbb_optimizations (gcc::context *ctxt)
+- : rtl_opt_pass (pass_data_bbb_optimizations, ctxt)
+- {}
+-
+- /* opt_pass methods: */
+- virtual bool gate (function *)
+- {
+- return true;
+- }
+-
+- virtual unsigned int execute (function *)
+- {
+- return execute_bbb_optimizations ();
+- }
+-
+- }; // class pass_bbb_optimizations
+-
+- } // anon namespace
++ /* opt_pass methods: */
++ virtual bool
++ gate (function *)
++ {
++ return TARGET_AMIGA;
++ }
++
++ virtual unsigned int
++ execute (function *)
++ {
++ return execute_bbb_optimizations ();
++ }
++
++ opt_pass *
++ clone ()
++ {
++ return new pass_bbb_optimizations (m_ctxt);
++ }
++
++ };
++// class pass_bbb_optimizations
++
++}// anon namespace
+
+ rtl_opt_pass *
+-make_pass_bbb_optimizations (gcc::context *ctxt)
+- {
+- return new pass_bbb_optimizations (ctxt);
+- }
++make_pass_bbb_optimizations (gcc::context * ctxt)
++{
++ return new pass_bbb_optimizations (ctxt);
++}
+diff --git a/gcc/passes.def b/gcc/passes.def
+index 45ff86c383e4..ca5b94552d4e 100644
+--- gcc/passes.def
++++ gcc/passes.def
+@@ -460,6 +460,7 @@ along with GCC; see the file COPYING3. If not see
+ NEXT_PASS (pass_stack_adjustments);
+ NEXT_PASS (pass_fast_rtl_dce);
+ NEXT_PASS (pass_reorder_blocks);
++ NEXT_PASS (pass_bbb_optimizations);
+ NEXT_PASS (pass_branch_target_load_optimize2);
+ NEXT_PASS (pass_leaf_regs);
+ NEXT_PASS (pass_split_before_sched2);
+
+From a56cbf57c5732afe7dfe0b67472284434ccfcbb2 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 5 Apr 2017 22:54:53 +0200
+Subject: [PATCH 054/303] @B fix resident options, add -fbbb
+
+---
+ gcc/config/m68k/amigaos.h | 2 +-
+ gcc/config/m68k/amigaos.opt | 10 +++++++---
+ 2 files changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h
+index ce47723e962f..49dd90d745c3 100644
+--- gcc/config/m68k/amigaos.h
++++ gcc/config/m68k/amigaos.h
+@@ -454,7 +454,7 @@ extern tree amigaos_handle_type_attribute(tree *, tree, tree, int, bool*);
+ #define SUBTARGET_OVERRIDE_OPTIONS \
+ do \
+ { \
+- if (!TARGET_68020 && flag_mybaserel==2) \
++ if (!TARGET_68020 && flag_pic==4) \
+ error ("-fbaserel32 is not supported on the 68000 or 68010\n"); \
+ if (amigaos_regparm > 0 && amigaos_regparm > AMIGAOS_MAX_REGPARM) \
+ error ("-mregparm=x with 1 <= x <= %d\n", AMIGAOS_MAX_REGPARM); \
+diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt
+index f985cf5e2845..2d8bed0a9103 100644
+--- gcc/config/m68k/amigaos.opt
++++ gcc/config/m68k/amigaos.opt
+@@ -32,13 +32,17 @@ Target Report Var(flag_pic,4)
+ data is adressed relativ to a4 with 32 bit offsets
+
+ resident
+-Target Common Report Var(flag_mybaserel,1)
++Target Common Report Var(flag_pic,3)
+ data is adressed relativ to a4, linked as resident
+
+ resident32
+-Target Common Report Var(flag_mybaserel,2)
++Target Common Report Var(flag_pic,4)
+ data is adressed relativ to a4 with 32 bit offsets, linked as resident
+
+ mcrt=
+ Target RejectNegative Var(amigaos_crt) Joined
+-Specify startup binary
+\ No newline at end of file
++Specify startup binary
++
++fbbb
++Target Var(flag_bbb_opts,1) UInteger Init(0)
++Enable Bebbo's optimizations
+
+From 01bd7d9ab157a9d973115a47cb9d24446f30f619 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 5 Apr 2017 22:55:25 +0200
+Subject: [PATCH 055/303] @I cleanup
+
+---
+ gcc/config/m68k/m68k.c | 10 ----------
+ 1 file changed, 10 deletions(-)
+
+diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
+index 6c0d9211598d..52eabeaafb23 100644
+--- gcc/config/m68k/m68k.c
++++ gcc/config/m68k/m68k.c
+@@ -2928,16 +2928,6 @@ m68k_rtx_costs (rtx x, machine_mode mode, int outer_code,
+ *total = COSTS_N_INSNS (TARGET_COLDFIRE ? 2 : 3);
+ return true;
+ }
+- /* reg + value */
+-// if (mode == SImode
+-// && REG_P(XEXP(x, 0))) {
+-// if (m68k_rtx_costs(XEXP(x, 1), mode, PLUS, 1, total, speed))
+-// {
+-// if (REGNO_REG_CLASS(REGNO(XEXP(x, 0))) == ADDR_REGS)
+-// *total += 4;
+-// return true;
+-// }
+-// }
+
+ return false;
+
+
+From ab8a4e993790f397307d8ec74581791e12470cf9 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 5 Apr 2017 23:00:59 +0200
+Subject: [PATCH 056/303] @B fix life analysis and commute_add_move, also some
+ cleanup
+
+---
+ gcc/bbb-opts.c | 314 +++++++++++++++++++++++++++++++++------------------------
+ 1 file changed, 180 insertions(+), 134 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 7fd01139d0f3..48e2fa3fd255 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -1,5 +1,6 @@
+ /* Bebbo's Optimizations.
+- Copyright (C) 2010-2016 Free Software Foundation, Inc.
++ Copyright (C) 2010-2017 Free Software Foundation, Inc.
++ Copyright (C) 2017 Stefan "Bebbo" Franke.
+
+ This file is part of GCC.
+
+@@ -26,14 +27,7 @@
+ * check if a->b->a can be moved out of a loop.
+ *
+ * #2 strcpy_opt
+- * move a,reg
+- * move reg,b
+- * cmp #0,reg
+- * jcc
+- *
+- * ->
+- * move a,b
+- * jcc
++ * check if a temp reg can be eliminated.
+ *
+ */
+
+@@ -55,39 +49,91 @@
+ #include <map>
+
+ /* enough for m68k. */
+-typedef unsigned insn_info; //[(FIRST_PSEUDO_REGISTER + sizeof(unsigned) * 8 - 1) / (sizeof(unsigned) * 8)];
+-
+-static inline void
+-resetii (unsigned & ii)
++struct insn_info
+ {
+- ii = 0;
+-}
++ unsigned mask;
+
+-static inline void
+-setii (unsigned regno, unsigned & ii)
+-{
+- ii |= 1 << regno;
+-}
++ insn_info () :
++ mask (0)
++ {
++ }
+
+-static inline void
+-clearii (unsigned regno, unsigned & ii)
+-{
+- ii &= ~(1 << regno);
+-}
++ inline void
++ reset ()
++ {
++ mask = 0;
++ }
+
+-static inline bool
+-getii (unsigned regno, unsigned & ii)
+-{
+- return ii & (1 << regno) ? true : false;
+-}
++ inline void
++ set (int regno)
++ {
++ mask |= 1 << regno;
++ }
++
++ inline void
++ unset (int regno)
++ {
++ mask &= ~(1 << regno);
++ }
++
++ inline bool
++ get (int regno)
++ {
++ return (mask & (1 << regno)) != 0;
++ }
++
++ inline insn_info
++ operator | (insn_info const & o) const
++ {
++ insn_info t;
++ t.mask = mask | o.mask;
++ return t;
++ }
++
++ inline insn_info
++ operator & (insn_info const & o) const
++ {
++ insn_info t;
++ t.mask = mask & o.mask;
++ return t;
++ }
++
++ inline insn_info &
++ operator |= (insn_info const & o)
++ {
++ mask |= o.mask;
++ return *this;
++ }
++
++ inline insn_info &
++ operator &= (insn_info const & o)
++ {
++ mask &= o.mask;
++ return *this;
++ }
++
++ inline bool
++ operator == (insn_info const & o)
++ {
++ return mask == o.mask;
++ }
++
++ inline insn_info
++ operator ~ () const
++ {
++ insn_info t;
++ t.mask = ~mask;
++ return t;
++ }
++};
+
+ /* scan rtx for registers. */
+ static void
+-scanii (rtx x, unsigned & ii)
++scanii (rtx x, insn_info & ii)
+ {
+ if (REG_P(x))
+ {
+- setii (REGNO(x), ii);
++ ii.set (REGNO(x));
+ return;
+ }
+
+@@ -117,61 +163,27 @@ clear (void)
+ infos.clear ();
+ }
+
+-static void
+-dump_costs (void)
+-{
+- rtx d0 = gen_raw_REG (SImode, 0);
+- rtx d0b = gen_raw_REG (QImode, 0);
+- rtx d1 = gen_raw_REG (SImode, 1);
+- rtx d1b = gen_raw_REG (QImode, 1);
+- rtx a0 = gen_raw_REG (SImode, 8);
+- rtx a1 = gen_raw_REG (SImode, 9);
+-
+- struct ICO
+- {
+- char const * name;
+- rtx set;
+- } data[] =
+- {
+- { "move d0,(a0)", gen_rtx_SET(gen_rtx_MEM (SImode, a0), d0) },
+- { "move a0,d0", gen_rtx_SET(d0, a0) },
+- { "move (a0),d0", gen_rtx_SET(d0, gen_rtx_MEM (SImode, a0)) },
+- { "move d0,(a0)", gen_rtx_SET(gen_rtx_MEM (SImode, a0), d0) },
+- { "move d1,(a1)+", gen_rtx_SET(d1, gen_rtx_MEM (SImode, gen_rtx_POST_INC (SImode, a1))) },
+- { "move (a0),(a1)", gen_rtx_SET(gen_rtx_MEM (SImode, a1), gen_rtx_MEM (SImode, a0)) },
+- { 0, 0 } }, *p;
+-
+- for (p = data; p->name; ++p)
+- {
+- int cost = insn_rtx_cost (p->set, true);
+- fprintf (stderr, "%s: %d\n", p->name, cost);
+- }
+-}
+-
+-
+ static void
+ dump_insns (char const * name)
+ {
+- rtx_insn *insn, *next;
+- fprintf(stderr, "====================================: %s\n", name);
+- for (unsigned i = 0; i < insns.size(); ++i)
++ fprintf (stderr, "====================================: %s\n", name);
++ for (unsigned i = 0; i < insns.size (); ++i)
+ {
+ insn_info & ii = infos[i];
+
+ for (int j = 0; j < 8; ++j)
+- if (getii(j, ii))
+- fprintf(stderr, "d%d ", j);
++ if (ii.get (j))
++ fprintf (stderr, "d%d ", j);
+
+ for (int j = 8; j < 16; ++j)
+- if (getii(j, ii))
+- fprintf(stderr, "a%d ", j-8);
++ if (ii.get (j))
++ fprintf (stderr, "a%d ", j - 8);
+
+- fprintf(stderr, "\t");
+- debug_rtx(insns[i]);
++ fprintf (stderr, "\t");
++ debug_rtx (insns[i]);
+ }
+ }
+
+-
+ /*
+ * Create a filtered view of insns - keep only those to work with.
+ */
+@@ -192,7 +204,7 @@ filter_insns ()
+ {
+ // debug_rtx (insn);
+ if (JUMP_P(insn))
+- jumps.push_back(insn);
++ jumps.push_back (insn);
+
+ insn2index.insert (std::make_pair (insn, insns.size ()));
+ insns.push_back (insn);
+@@ -201,13 +213,12 @@ filter_insns ()
+
+ /* prepare insn_info */
+ insn_info ii;
+- resetii (ii);
+ for (unsigned i = 0; i < insns.size (); ++i)
+ {
+ infos.push_back (ii);
+ }
+
+- /* own analyze life */
++ /* own analyze reg life */
+ std::vector<std::pair<unsigned, insn_info>> todo;
+ todo.push_back (std::make_pair (insns.size () - 1, ii));
+
+@@ -236,53 +247,40 @@ filter_insns ()
+ if (JUMP_LABEL(*i) == insn)
+ {
+ std::map<rtx_insn *, unsigned>::iterator j = insn2index.find (*i);
+- if (j != insn2index.end())
++ if (j != insn2index.end ())
+ todo.push_back (std::make_pair (j->second, ii));
+ }
+ }
+ continue;
+ }
+
+- rtx set = single_set (insn);
+- if (set == 0)
+- {
+- if (JUMP_P(insn)) {
+- resetii(ii);
+- setii(0, ii);
+- infos[pos] = ii;
+- continue;
+- }
+- fprintf(stderr, "##### ");
+- debug_rtx(insn);
+- continue;
+- }
+-
+- rtx src = SET_SRC(set);
+- rtx dst = SET_DEST(set);
+-
+- debug_rtx(insn);
++ rtx pattern = PATTERN (insn);
+
+ if (CALL_P(insn))
+ {
+ /* a call sets d0 and kills d1,a0,a1. */
+- if (getii (1, ii))
++ if (ii.get (1))
+ fprintf (stderr, "d1 used after call\n");
+- if (getii (8, ii))
++ if (ii.get (8))
+ fprintf (stderr, "a0 used after call\n");
+- if (getii (9, ii))
++ if (ii.get (9))
+ fprintf (stderr, "a1 used after call\n");
+
+- resetii (ii);
++ ii.unset(0);
++ ii.unset(1);
++ ii.unset(8);
++ ii.unset(9);
++
++ // FIXME: get the DECL and read attributes.
+ // use regs depending on flag mregparm
+ for (int i = 0; i < amigaos_regparm; ++i)
+ {
+- setii (i, ii);
+- setii (i + 8, ii);
++ ii.set (i);
++ ii.set (i + 8);
+ }
+
+ // check for reg use
+- if (REG_P(src))
+- setii (REGNO(src), ii);
++ scanii (pattern, ii);
+
+ infos[pos] = ii;
+ continue;
+@@ -290,37 +288,55 @@ filter_insns ()
+
+ if (JUMP_P(insn))
+ {
+- if (ANY_RETURN_P(src))
++ if (ANY_RETURN_P(pattern))
+ {
+- resetii (ii);
+- setii (0, ii);
++ ii.reset ();
++ ii.set (0);
+ }
+ else
+ {
+ ii |= infos[pos];
+
+ // check for reg use
+- if (REG_P(src))
+- setii (REGNO(src), ii);
++ scanii(PATTERN(insn), ii);
++
++ }
++ infos[pos] = ii;
++ continue;
++ }
++
+
++ rtx set = single_set (insn);
++ if (set == 0)
++ {
++ if (GET_CODE (pattern) == USE)
++ {
++ rtx x = XEXP(pattern, 0);
++ if (REG_P(x))
++ ii.set(REGNO(x));
++ infos[pos] = ii;
++ continue;
+ }
++
++ fprintf (stderr, "##### ");
++ debug_rtx (insn);
++ scanii (pattern, ii);
+ infos[pos] = ii;
+ continue;
+ }
+
++ rtx src = SET_SRC(set);
++ rtx dst = SET_DEST(set);
+ // scan insn for regs
+ // a def stop propagation
+ // a use starts propagation
+ // also add use to current ii
+ insn_info use;
+- resetii (use);
+-
+ insn_info def;
+- resetii (def);
+
+ scanii (src, use);
+ if (REG_P(dst))
+- setii (REGNO(dst), def);
++ def.set (REGNO(dst));
+ else
+ scanii (dst, use);
+
+@@ -808,16 +824,16 @@ commute_add_move (void)
+ if (!set)
+ continue;
+
+- rtx reg1 = SET_DEST(set);
+- if (!REG_P(reg1))
++ rtx reg1dst = SET_DEST(set);
++ if (!REG_P(reg1dst))
+ continue;
+
+ rtx plus = SET_SRC(set);
+ if (GET_CODE(plus) != PLUS)
+ continue;
+
+- rtx reg2 = XEXP(plus, 0);
+- if (!REG_P(reg2))
++ rtx reg1src = XEXP(plus, 0);
++ if (!REG_P(reg1src) || reg1src == reg1dst)
+ continue;
+
+ rtx cnst = XEXP(plus, 1);
+@@ -834,35 +850,35 @@ commute_add_move (void)
+ continue;
+
+ rtx memreg = XEXP(dst, 0);
+- if (!REG_P(memreg) || REGNO(memreg) != REGNO(reg2))
++ if (!REG_P(memreg) || REGNO(memreg) != REGNO(reg1src))
+ continue;
+
+ int oldcost1 = insn_rtx_cost (set, true);
+ int oldcost2 = insn_rtx_cost (set2, true);
+
+- fprintf (stderr, "commute_add_move found, oldcost: %d = %d + %d\n", oldcost1 + oldcost2, oldcost1, oldcost2);
++ fprintf (stderr, "commute_add_move found, old cost: %d = %d + %d\n", oldcost1 + oldcost2, oldcost1, oldcost2);
+
+- //debug_rtx (insn);
+- //debug_rtx (next);
++ debug_rtx (insn);
++ debug_rtx (next);
+
+- rtx pinc = gen_rtx_POST_INC(GET_MODE(dst), reg1);
++ rtx pinc = gen_rtx_POST_INC(GET_MODE(dst), reg1dst);
+ rtx newmem = replace_equiv_address_nv (dst, pinc);
+
+ if (validate_change (next, &SET_DEST(set2), newmem, 0))
+ {
+ SET_INSN_DELETED(insn);
+
+- insn = emit_insn_before (gen_movsi (reg1, reg2), next);
++ insn = emit_insn_before (gen_movsi (reg1dst, reg1src), next);
+
+- add_reg_note (next, REG_INC, reg1);
++ add_reg_note (next, REG_INC, reg1dst);
+
+ int newcost1 = insn_rtx_cost (set, true);
+ int newcost2 = insn_rtx_cost (set2, true);
+
+- fprintf (stderr, "commute_add_move found, newcost: %d = %d + %d\n", newcost1 + newcost2, newcost1, newcost2);
++ fprintf (stderr, "commute_add_move found, new cost: %d = %d + %d\n", newcost1 + newcost2, newcost1, newcost2);
+
+- //debug_rtx (insn);
+- //debug_rtx (next);
++ debug_rtx (insn);
++ debug_rtx (next);
+
+ df_insn_rescan (insn);
+ df_insn_rescan (next);
+@@ -889,13 +905,43 @@ const_cmp_to_sub (void)
+ if (dst != cc0_rtx)
+ continue;
+
+- fprintf (stderr, "cc0:");
+- debug_rtx (insn);
++// fprintf (stderr, "cc0:");
++// debug_rtx (insn);
+ }
+ #endif
+ return change_count;
+ }
+
++static unsigned
++elim_dead_assign (void)
++{
++ unsigned change_count = 0;
++ for (unsigned index = 0; index + 1 < insns.size (); ++index)
++ {
++ rtx_insn * insn = insns[index];
++ if (!NONJUMP_INSN_P(insn))
++ continue;
++
++ rtx set = single_set (insn);
++ if (!set)
++ continue;
++
++ rtx src = SET_SRC(set);
++ rtx dst = SET_DEST(set);
++ if (!REG_P(dst) || !REG_P(src))
++ continue;
++
++ if (!infos[index].get (REGNO(dst)))
++ {
++ fprintf (stderr, "eliminate dead assignment to %d:", REGNO(dst));
++ debug_rtx (insn);
++ SET_INSN_DELETED(insn);
++ ++change_count;
++ }
++ }
++ return change_count;
++}
++
+ /* Main entry point to the pass. */
+ static unsigned int
+ execute_bbb_optimizations (void)
+@@ -904,7 +950,6 @@ execute_bbb_optimizations (void)
+ df_note_add_problem ();
+ df_analyze ();
+
+-// dump_insns ("bbb 0");
+ filter_insns ();
+
+ for (;;)
+@@ -925,15 +970,16 @@ execute_bbb_optimizations (void)
+ if (const_cmp_to_sub ())
+ done = 0, filter_insns ();
+
++ if (elim_dead_assign ())
++ done = 0, filter_insns ();
++
+ if (done)
+ break;
+ }
+
+- dump_insns ("bbb 1");
++// dump_insns ("bbb 1");
+ clear ();
+
+- dump_costs ();
+-
+ return 0;
+ }
+
+@@ -964,7 +1010,7 @@ namespace
+ virtual bool
+ gate (function *)
+ {
+- return TARGET_AMIGA;
++ return TARGET_AMIGA && flag_bbb_opts;
+ }
+
+ virtual unsigned int
+
+From f5cd54a27e20a9ef7b1ec441fad9486216a87253 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 6 Apr 2017 13:41:46 +0200
+Subject: [PATCH 057/303] @N const_cmp_to_sub
+
+---
+ gcc/bbb-opts.c | 187 ++++++++++++++++++++++++++++++++++++++++++++-------------
+ 1 file changed, 146 insertions(+), 41 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 48e2fa3fd255..44616bcabd6b 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -48,7 +48,9 @@
+ #include <vector>
+ #include <map>
+
+-/* enough for m68k. */
++/* Enough for m68k.
++ * Why a class? Maybe extend it for general usage.
++ */
+ struct insn_info
+ {
+ unsigned mask;
+@@ -127,7 +129,7 @@ struct insn_info
+ }
+ };
+
+-/* scan rtx for registers. */
++/* scan rtx for registers and set the corresponding flags. */
+ static void
+ scanii (rtx x, insn_info & ii)
+ {
+@@ -149,11 +151,17 @@ scanii (rtx x, insn_info & ii)
+ }
+ }
+
++/*
++ * Collect some data.
++ */
+ static std::vector<rtx_insn *> insns;
+ static std::vector<rtx_insn *> jumps;
+ static std::map<rtx_insn *, unsigned> insn2index;
+ static std::vector<insn_info> infos;
+
++/*
++ * Reset collected data.
++ */
+ static void
+ clear (void)
+ {
+@@ -163,6 +171,10 @@ clear (void)
+ infos.clear ();
+ }
+
++/*
++ * Helper function to dump the code.
++ * Sometimes used during debugging.
++ */
+ static void
+ dump_insns (char const * name)
+ {
+@@ -188,7 +200,7 @@ dump_insns (char const * name)
+ * Create a filtered view of insns - keep only those to work with.
+ */
+ static void
+-filter_insns ()
++update_meta_data ()
+ {
+ rtx_insn *insn, *next;
+ clear ();
+@@ -258,18 +270,11 @@ filter_insns ()
+
+ if (CALL_P(insn))
+ {
+- /* a call sets d0 and kills d1,a0,a1. */
+- if (ii.get (1))
+- fprintf (stderr, "d1 used after call\n");
+- if (ii.get (8))
+- fprintf (stderr, "a0 used after call\n");
+- if (ii.get (9))
+- fprintf (stderr, "a1 used after call\n");
+-
+- ii.unset(0);
+- ii.unset(1);
+- ii.unset(8);
+- ii.unset(9);
++ /* a call sets d0 and maybe also d1,a0,a1. */
++ ii.unset (0);
++ ii.unset (1);
++ ii.unset (8);
++ ii.unset (9);
+
+ // FIXME: get the DECL and read attributes.
+ // use regs depending on flag mregparm
+@@ -298,14 +303,13 @@ filter_insns ()
+ ii |= infos[pos];
+
+ // check for reg use
+- scanii(PATTERN(insn), ii);
++ scanii (PATTERN (insn), ii);
+
+ }
+ infos[pos] = ii;
+ continue;
+ }
+
+-
+ rtx set = single_set (insn);
+ if (set == 0)
+ {
+@@ -313,13 +317,16 @@ filter_insns ()
+ {
+ rtx x = XEXP(pattern, 0);
+ if (REG_P(x))
+- ii.set(REGNO(x));
++ ii.set (REGNO(x));
+ infos[pos] = ii;
+ continue;
+ }
+
+- fprintf (stderr, "##### ");
+- debug_rtx (insn);
++ if (GET_CODE (pattern) != PARALLEL)
++ {
++ fprintf (stderr, "##### ");
++ debug_rtx (insn);
++ }
+ scanii (pattern, ii);
+ infos[pos] = ii;
+ continue;
+@@ -501,7 +508,7 @@ propagate_moves ()
+ {
+ std::vector<rtx_insn *>::iterator label_iter = jump_out.begin ();
+ int fixup = 0;
+- fprintf (stderr, "need %d jump out fixups\n", jump_out.size ());
++ fprintf (stderr, ": need %d jump out fixups\n", jump_out.size ());
+
+ for (unsigned k = *i + 1; k != *j; ++k)
+ {
+@@ -574,7 +581,7 @@ propagate_moves ()
+ rtx_insn * after = insns[index + 1];
+ rtx bset = single_set (before);
+
+- fprintf (stderr, "condition met, moving regs %d, %d\n", REGNO(srci), REGNO(dsti));
++ fprintf (stderr, ": condition met, moving regs %d, %d\n", REGNO(srci), REGNO(dsti));
+
+ /* Move in front of loop and mark as dead. */
+ remove_insn (ii);
+@@ -607,7 +614,7 @@ propagate_moves ()
+ /* add fixes if there were jumps out of the loop. */
+ if (jump_out.size ())
+ {
+- fprintf (stderr, "fixing %d jump outs\n", jump_out.size ());
++ fprintf (stderr, ": fixing %d jump outs\n", jump_out.size ());
+
+ for (unsigned k = 0; k < jump_out.size (); ++k)
+ {
+@@ -698,7 +705,7 @@ opt_strcpy ()
+
+ fprintf (
+ stderr,
+- "condition met, removing compare and joining insns - omit reg %d\n", REGNO(dst));
++ ": condition met, removing compare and joining insns - omit reg %d\n", REGNO(dst));
+
+ for (link = REG_NOTES(x2reg); link; link = XEXP(link, 1))
+ if (REG_NOTE_KIND (link) != REG_LABEL_OPERAND)
+@@ -856,7 +863,7 @@ commute_add_move (void)
+ int oldcost1 = insn_rtx_cost (set, true);
+ int oldcost2 = insn_rtx_cost (set2, true);
+
+- fprintf (stderr, "commute_add_move found, old cost: %d = %d + %d\n", oldcost1 + oldcost2, oldcost1, oldcost2);
++ fprintf (stderr, ": commute_add_move found, old cost: %d = %d + %d\n", oldcost1 + oldcost2, oldcost1, oldcost2);
+
+ debug_rtx (insn);
+ debug_rtx (next);
+@@ -875,7 +882,7 @@ commute_add_move (void)
+ int newcost1 = insn_rtx_cost (set, true);
+ int newcost2 = insn_rtx_cost (set2, true);
+
+- fprintf (stderr, "commute_add_move found, new cost: %d = %d + %d\n", newcost1 + newcost2, newcost1, newcost2);
++ fprintf (stderr, ": commute_add_move found, new cost: %d = %d + %d\n", newcost1 + newcost2, newcost1, newcost2);
+
+ debug_rtx (insn);
+ debug_rtx (next);
+@@ -889,24 +896,122 @@ commute_add_move (void)
+ return change_count;
+ }
+
++/*
++ * Replace
++ *
++ * move x,dx
++ * cmp dx,dy
++ *
++ * if dx and dy are both dead after compare.
++ *
++ * with
++ *
++ * sub #n,dx
++ *
++ d0 d1 d2 a0 a1 a7 (insn 99 59 41 7 (set (reg:SI 2 d2)
++ (const_int 1 [0x1])) sn.c:8 38 {*movsi_m68k}
++ (nil))
++ d0 d1 d2 a0 a1 a7 (insn 41 99 42 7 (set (cc0)
++ (compare (reg/v:SI 1 d1 [orig:54 n ] [54])
++ (reg:SI 2 d2))) sn.c:8 16 {*m68k.md:499}
++ (expr_list:REG_DEAD (reg:SI 2 d2)
++ (expr_list:REG_DEAD (reg/v:SI 1 d1 [orig:54 n ] [54])
++ (nil))))
++ *
++ */
+ static unsigned
+ const_cmp_to_sub (void)
+ {
+ unsigned change_count = 0;
+ #if HAVE_cc0
+- for (unsigned index = 0; index + 1 < insns.size (); ++index)
++ for (unsigned index = 1; index + 1 < insns.size (); ++index)
+ {
+ rtx_insn * insn = insns[index];
+- rtx set = single_set (insn);
+- if (!set)
++ rtx seti = single_set (insn);
++ if (!seti)
+ continue;
+
+- rtx dst = SET_DEST(set);
+- if (dst != cc0_rtx)
++ rtx dsti = SET_DEST(seti);
++ if (dsti != cc0_rtx)
++ continue;
++
++ rtx srci = SET_SRC(seti);
++ if (GET_CODE(srci) != COMPARE)
++ continue;
++
++ rtx left = XEXP(srci, 0);
++ rtx right = XEXP(srci, 1);
++ if (!REG_P(left) || !REG_P(right))
+ continue;
+
+-// fprintf (stderr, "cc0:");
+-// debug_rtx (insn);
++ if (!find_reg_note (insn, REG_DEAD, left) || !find_reg_note (insn, REG_DEAD, right))
++ continue;
++
++ fprintf (stderr, ": found reg-reg compare with both dead\n");
++
++ // maybe add a search?
++ rtx_insn * prev = insns[index - 1];
++ rtx setp = single_set (prev);
++ if (!setp)
++ continue;
++
++ rtx dstp = SET_DEST(setp);
++ if (!REG_P(dstp) || dstp != left)
++ continue;
++
++ rtx srcp = SET_SRC(setp);
++ if (!CONST_INT_P(srcp))
++ continue;
++
++ int intval = -INTVAL(srcp);
++ if (intval < -8 || intval > 7)
++ continue;
++
++ enum machine_mode mode = GET_MODE(dstp);
++ rtx reg = dstp == left ? right : left;
++ rtx plus = gen_rtx_PLUS(mode, reg, gen_rtx_CONST_INT(mode, intval));
++
++ SET_SRC(setp) = plus;
++ SET_DEST(setp) = reg;
++
++ int num_clobbers_to_add = 0;
++ int insn_code_number = recog (PATTERN (prev), prev, &num_clobbers_to_add);
++
++ SET_SRC(setp) = srcp;
++ SET_DEST(setp) = dstp;
++
++ if (insn_code_number < 0)
++ continue;
++
++ debug_rtx(prev);
++ debug_rtx(insn);
++
++ // also convert current statement to cmp #0, reg
++ SET_INSN_DELETED(insn);
++ rtx neu = gen_rtx_SET(cc0_rtx, gen_rtx_COMPARE(mode, reg, gen_rtx_CONST_INT(mode, 0)));
++ insn = emit_insn_after(neu, prev);
++ add_reg_note (insn, REG_DEAD, reg);
++
++ SET_INSN_DELETED(prev);
++ neu = gen_rtx_SET(reg, plus);
++ prev = emit_insn_before(neu, insn);
++
++ int omitted_regno = REGNO(dstp == left ? left: right);
++ if (!(df->hard_regs_live_count[omitted_regno] -= 2))
++ df_set_regs_ever_live (omitted_regno, false);
++
++ fprintf (stderr, ": replaced reg-reg compare with sub\n");
++ debug_rtx(prev);
++ debug_rtx(insn);
++
++ if (dstp != left)
++ {
++ // invert all conditions using this statement.
++
++ }
++
++
++ ++change_count;
+ }
+ #endif
+ return change_count;
+@@ -933,7 +1038,7 @@ elim_dead_assign (void)
+
+ if (!infos[index].get (REGNO(dst)))
+ {
+- fprintf (stderr, "eliminate dead assignment to %d:", REGNO(dst));
++ fprintf (stderr, ": eliminate dead assignment to %d:", REGNO(dst));
+ debug_rtx (insn);
+ SET_INSN_DELETED(insn);
+ ++change_count;
+@@ -950,28 +1055,28 @@ execute_bbb_optimizations (void)
+ df_note_add_problem ();
+ df_analyze ();
+
+- filter_insns ();
++ update_meta_data ();
+
+ for (;;)
+ {
+ int done = 1;
+ if (propagate_moves ())
+- done = 0, filter_insns ();
++ done = 0, update_meta_data ();
+
+ if (offset_2_autoinc ())
+- done = 0, filter_insns ();
++ done = 0, update_meta_data ();
+
+ if (opt_strcpy ())
+- done = 0, filter_insns ();
++ done = 0, update_meta_data ();
+
+ if (commute_add_move ())
+- done = 0, filter_insns ();
++ done = 0, update_meta_data ();
+
+ if (const_cmp_to_sub ())
+- done = 0, filter_insns ();
++ done = 0, update_meta_data ();
+
+ if (elim_dead_assign ())
+- done = 0, filter_insns ();
++ done = 0, update_meta_data ();
+
+ if (done)
+ break;
+
+From 485cc891b48af316e84f77e6142a0c28b80c596d Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 6 Apr 2017 22:05:20 +0200
+Subject: [PATCH 058/303] @N const_cmp_to_sub seems working
+
+---
+ gcc/bbb-opts.c | 249 ++++++++++++++++++++++++++++++++++++++++++++-------------
+ 1 file changed, 192 insertions(+), 57 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 44616bcabd6b..8a98fbfaad7c 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -50,45 +50,64 @@
+
+ /* Enough for m68k.
+ * Why a class? Maybe extend it for general usage.
++ *
++ * Track use & def separate to determine starting points.
+ */
+ struct insn_info
+ {
+- unsigned mask;
++ unsigned _use;
++ unsigned _def;
+
+ insn_info () :
+- mask (0)
++ _use (0), _def (0)
+ {
+ }
+
+ inline void
+ reset ()
+ {
+- mask = 0;
++ _use = 0;
++ _def = 0;
+ }
+
+ inline void
+- set (int regno)
++ use (int regno)
+ {
+- mask |= 1 << regno;
++ _use |= 1 << regno;
++ }
++
++ inline void
++ def (int regno)
++ {
++ _use |= 1 << regno;
++ _def |= 1 << regno;
+ }
+
+ inline void
+ unset (int regno)
+ {
+- mask &= ~(1 << regno);
++ _use &= ~(1 << regno);
++ _def &= ~(1 << regno);
+ }
+
+ inline bool
+- get (int regno)
++ is_use (int regno)
+ {
+- return (mask & (1 << regno)) != 0;
++ return (_use & (1 << regno)) != 0;
++ }
++
++ inline bool
++ is_def (int regno)
++ {
++ return (_def & (1 << regno)) != 0;
+ }
+
+ inline insn_info
+ operator | (insn_info const & o) const
+ {
+ insn_info t;
+- t.mask = mask | o.mask;
++ t._use = _use | o._use;
++ t._def = _def | o._def;
+ return t;
+ }
+
+@@ -96,46 +115,67 @@ struct insn_info
+ operator & (insn_info const & o) const
+ {
+ insn_info t;
+- t.mask = mask & o.mask;
++ t._use = _use & o._use;
++ t._def = _def & o._def;
+ return t;
+ }
+
+ inline insn_info &
+ operator |= (insn_info const & o)
+ {
+- mask |= o.mask;
++ _use |= o._use;
++ _def |= o._def;
+ return *this;
+ }
+
+ inline insn_info &
+ operator &= (insn_info const & o)
+ {
+- mask &= o.mask;
++ _use &= o._use;
++ _def &= o._def;
+ return *this;
+ }
+
+ inline bool
+ operator == (insn_info const & o)
+ {
+- return mask == o.mask;
++ return _use == o._use;
+ }
+
+ inline insn_info
+ operator ~ () const
+ {
+ insn_info t;
+- t.mask = ~mask;
++ t._use = ~_use;
++ t._def = ~_def;
+ return t;
+ }
++
++ inline bool contains(insn_info const & o) const {
++ if (o._def & ~_def)
++ return false;
++ if (o._use & ~_use)
++ return false;
++ return true;
++ }
++
++ void
++ scan (rtx);
+ };
+
+ /* scan rtx for registers and set the corresponding flags. */
+-static void
+-scanii (rtx x, insn_info & ii)
++void
++insn_info::scan (rtx x)
+ {
+ if (REG_P(x))
+ {
+- ii.set (REGNO(x));
++ use (REGNO(x));
++ return;
++ }
++
++ if (x == cc0_rtx)
++ {
++ use (FIRST_PSEUDO_REGISTER);
+ return;
+ }
+
+@@ -144,10 +184,10 @@ scanii (rtx x, insn_info & ii)
+ for (int i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'e')
+- scanii (XEXP(x, i), ii);
++ scan (XEXP(x, i));
+ else if (fmt[i] == 'E')
+ for (int j = XVECLEN (x, i) - 1; j >= 0; j--)
+- scanii (XVECEXP(x, i, j), ii);
++ scan (XVECEXP(x, i, j));
+ }
+ }
+
+@@ -171,6 +211,23 @@ clear (void)
+ infos.clear ();
+ }
+
++static bool is_reg_dead(unsigned regno, unsigned pos)
++{
++ if (pos >= infos.size())
++ return true;
++
++ insn_info & ii0 = infos[pos++];
++ if (!ii0.is_use(regno))
++ return true;
++
++ if (pos >= infos.size())
++ return true;
++
++ insn_info & ii1 = infos[pos];
++
++ return !ii1.is_use(regno);
++}
++
+ /*
+ * Helper function to dump the code.
+ * Sometimes used during debugging.
+@@ -184,12 +241,15 @@ dump_insns (char const * name)
+ insn_info & ii = infos[i];
+
+ for (int j = 0; j < 8; ++j)
+- if (ii.get (j))
+- fprintf (stderr, "d%d ", j);
++ if (ii.is_use (j))
++ fprintf (stderr, ii.is_def (j) ? "*d%d " : "d%d ", j);
+
+ for (int j = 8; j < 16; ++j)
+- if (ii.get (j))
+- fprintf (stderr, "a%d ", j - 8);
++ if (ii.is_use (j))
++ fprintf (stderr, ii.is_def (j) ? "*a%d " : "a%d ", j - 8);
++
++ if (ii.is_use (FIRST_PSEUDO_REGISTER))
++ fprintf (stderr, ii.is_def (FIRST_PSEUDO_REGISTER) ? "*cc " : "cc ");
+
+ fprintf (stderr, "\t");
+ debug_rtx (insns[i]);
+@@ -246,7 +306,7 @@ update_meta_data ()
+ {
+ rtx_insn * insn = insns[pos];
+
+- if (pass && ii == infos[pos])
++ if (pass && infos[pos].contains(ii))
+ break;
+
+ ii |= infos[pos];
+@@ -276,16 +336,16 @@ update_meta_data ()
+ ii.unset (8);
+ ii.unset (9);
+
+- // FIXME: get the DECL and read attributes.
++ // FIXME: isuse the DECL and read attributes.
+ // use regs depending on flag mregparm
+ for (int i = 0; i < amigaos_regparm; ++i)
+ {
+- ii.set (i);
+- ii.set (i + 8);
++ ii.use (i);
++ ii.use (i + 8);
+ }
+
+ // check for reg use
+- scanii (pattern, ii);
++ ii.scan (pattern);
+
+ infos[pos] = ii;
+ continue;
+@@ -296,14 +356,14 @@ update_meta_data ()
+ if (ANY_RETURN_P(pattern))
+ {
+ ii.reset ();
+- ii.set (0);
++ ii.use (0);
+ }
+ else
+ {
+ ii |= infos[pos];
+
+ // check for reg use
+- scanii (PATTERN (insn), ii);
++ ii.scan (PATTERN (insn));
+
+ }
+ infos[pos] = ii;
+@@ -317,7 +377,7 @@ update_meta_data ()
+ {
+ rtx x = XEXP(pattern, 0);
+ if (REG_P(x))
+- ii.set (REGNO(x));
++ ii.use (REGNO(x));
+ infos[pos] = ii;
+ continue;
+ }
+@@ -327,7 +387,7 @@ update_meta_data ()
+ fprintf (stderr, "##### ");
+ debug_rtx (insn);
+ }
+- scanii (pattern, ii);
++ ii.scan (pattern);
+ infos[pos] = ii;
+ continue;
+ }
+@@ -341,13 +401,23 @@ update_meta_data ()
+ insn_info use;
+ insn_info def;
+
+- scanii (src, use);
++ use.scan (src);
+ if (REG_P(dst))
+- def.set (REGNO(dst));
++ def.def (REGNO(dst));
++ else if (dst == cc0_rtx)
++ def.def (FIRST_PSEUDO_REGISTER);
+ else
+- scanii (dst, use);
++ use.scan (dst);
+
+- infos[pos] = use | ii;
++ if (dst != cc0_rtx)
++ {
++ CC_STATUS_INIT;
++ NOTICE_UPDATE_CC(PATTERN (insn), insn);
++ if (cc_status.value1 || cc_status.value2)
++ def.def (FIRST_PSEUDO_REGISTER);
++ }
++
++ infos[pos] = def | use | ii;
+
+ ii &= ~def;
+ ii |= use;
+@@ -778,15 +848,15 @@ offset_2_autoinc (void)
+ if (!NONJUMP_INSN_P(insn))
+ continue;
+
+- rtx set = single_set (insn);
+- if (!set)
++ rtx use = single_set (insn);
++ if (!use)
+ continue;
+
+- rtx reg = SET_DEST(set);
++ rtx reg = SET_DEST(use);
+ if (!REG_P(reg))
+ continue;
+
+- rtx val = SET_SRC(set);
++ rtx val = SET_SRC(use);
+
+ // fprintf(stderr, "possible start for offset_2_autoinc\n");
+ // //debug_rtx(insn);
+@@ -882,7 +952,8 @@ commute_add_move (void)
+ int newcost1 = insn_rtx_cost (set, true);
+ int newcost2 = insn_rtx_cost (set2, true);
+
+- fprintf (stderr, ": commute_add_move found, new cost: %d = %d + %d\n", newcost1 + newcost2, newcost1, newcost2);
++ fprintf (stderr, ": commute_add_move found, new cost: %d = %d + %d\n", newcost1 + newcost2, newcost1,
++ newcost2);
+
+ debug_rtx (insn);
+ debug_rtx (next);
+@@ -944,10 +1015,14 @@ const_cmp_to_sub (void)
+ if (!REG_P(left) || !REG_P(right))
+ continue;
+
+- if (!find_reg_note (insn, REG_DEAD, left) || !find_reg_note (insn, REG_DEAD, right))
+- continue;
++// if (!find_reg_note (insn, REG_DEAD, left) || !find_reg_note (insn, REG_DEAD, right))
++// continue;
+
+- fprintf (stderr, ": found reg-reg compare with both dead\n");
++ if (!is_reg_dead(REGNO(left), index) || !is_reg_dead(REGNO(right), index))
++ continue;
++
++ fprintf (stderr, ": found reg-reg compare with both dead: %d %d\n",
++ is_reg_dead(REGNO(left), index), is_reg_dead(REGNO(right), index));
+
+ // maybe add a search?
+ rtx_insn * prev = insns[index - 1];
+@@ -956,7 +1031,7 @@ const_cmp_to_sub (void)
+ continue;
+
+ rtx dstp = SET_DEST(setp);
+- if (!REG_P(dstp) || dstp != left)
++ if (!REG_P(dstp))
+ continue;
+
+ rtx srcp = SET_SRC(setp);
+@@ -969,7 +1044,7 @@ const_cmp_to_sub (void)
+
+ enum machine_mode mode = GET_MODE(dstp);
+ rtx reg = dstp == left ? right : left;
+- rtx plus = gen_rtx_PLUS(mode, reg, gen_rtx_CONST_INT(mode, intval));
++ rtx plus = gen_rtx_PLUS(mode, reg, gen_rtx_CONST_INT (mode, intval));
+
+ SET_SRC(setp) = plus;
+ SET_DEST(setp) = reg;
+@@ -983,33 +1058,93 @@ const_cmp_to_sub (void)
+ if (insn_code_number < 0)
+ continue;
+
+- debug_rtx(prev);
+- debug_rtx(insn);
++ debug_rtx (prev);
++ debug_rtx (insn);
+
+ // also convert current statement to cmp #0, reg
+ SET_INSN_DELETED(insn);
+ rtx neu = gen_rtx_SET(cc0_rtx, gen_rtx_COMPARE(mode, reg, gen_rtx_CONST_INT(mode, 0)));
+- insn = emit_insn_after(neu, prev);
++ insn = emit_insn_after (neu, prev);
+ add_reg_note (insn, REG_DEAD, reg);
+
+ SET_INSN_DELETED(prev);
+ neu = gen_rtx_SET(reg, plus);
+- prev = emit_insn_before(neu, insn);
++ prev = emit_insn_before (neu, insn);
+
+- int omitted_regno = REGNO(dstp == left ? left: right);
+- if (!(df->hard_regs_live_count[omitted_regno] -= 2))
+- df_set_regs_ever_live (omitted_regno, false);
++// urks - unknown side effects
++// int omitted_regno = REGNO(dstp);
++// if (!(df->hard_regs_live_count[omitted_regno] -= 2))
++// df_set_regs_ever_live (omitted_regno, false);
+
+ fprintf (stderr, ": replaced reg-reg compare with sub\n");
+- debug_rtx(prev);
+- debug_rtx(insn);
++ debug_rtx (prev);
++ debug_rtx (insn);
+
+ if (dstp != left)
+ {
+ // invert all conditions using this statement.
++ std::vector<unsigned> todo;
++ std::vector<unsigned> done;
++ done.resize(insns.size());
++ todo.push_back (index + 1);
+
+- }
++ while (todo.size ())
++ {
++ unsigned pos = todo[todo.size () - 1];
++ todo.pop_back ();
++
++ if (done[pos])
++ continue;
+
++ done[pos] = 1;
++
++ if (infos[pos].is_def (FIRST_PSEUDO_REGISTER))
++ continue;
++
++ if (pos + 1 < infos.size ())
++ todo.push_back (pos + 1);
++
++ rtx_insn * patchme = insns[pos];
++ if (!JUMP_P(insn))
++ continue;
++
++ std::map<rtx_insn *, unsigned>::iterator j = insn2index.find ((rtx_insn *) JUMP_LABEL(patchme));
++ if (j != insn2index.end ())
++ todo.push_back (j->second);
++
++ rtx jmppattern = PATTERN (patchme);
++
++ rtx jmpsrc = XEXP(jmppattern, 1);
++ if (GET_CODE(jmpsrc) == IF_THEN_ELSE)
++ {
++ rtx condition = XEXP(jmpsrc, 0);
++ RTX_CODE code = GET_CODE(condition);
++ RTX_CODE newcode = code;
++ if (code == GE)
++ newcode = LE;
++ else if (code == GT)
++ newcode = LT;
++ else if (code == LT)
++ newcode = GT;
++ else if (code == LE)
++ newcode = GE;
++ else if (code == GEU)
++ newcode = LEU;
++ else if (code == GTU)
++ newcode = LTU;
++ else if (code == LTU)
++ newcode = GTU;
++ else if (code == LEU)
++ newcode = GEU;
++
++ if (code != newcode)
++ {
++ fprintf (stderr, ": patch jcc %d -> %d\n", code, newcode);
++ XEXP(jmpsrc, 0) = gen_rtx_fmt_ee(newcode, VOIDmode, XEXP(condition, 0), XEXP(condition, 1));
++ }
++ }
++ }
++ }
+
+ ++change_count;
+ }
+@@ -1036,7 +1171,7 @@ elim_dead_assign (void)
+ if (!REG_P(dst) || !REG_P(src))
+ continue;
+
+- if (!infos[index].get (REGNO(dst)))
++ if (!infos[index].is_use (REGNO(dst)))
+ {
+ fprintf (stderr, ": eliminate dead assignment to %d:", REGNO(dst));
+ debug_rtx (insn);
+
+From 9967eed30e2e8f28bb48aa5a39d1cd578d4e0a7a Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 7 Apr 2017 04:03:53 +0200
+Subject: [PATCH 059/303] @B avoid illegal insns
+
+---
+ gcc/bbb-opts.c | 188 ++++++++++++++++++++++++++++++++++++++++-----------------
+ 1 file changed, 132 insertions(+), 56 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 8a98fbfaad7c..d9e77c53856d 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -79,7 +79,6 @@ struct insn_info
+ inline void
+ def (int regno)
+ {
+- _use |= 1 << regno;
+ _def |= 1 << regno;
+ }
+
+@@ -151,7 +150,9 @@ struct insn_info
+ return t;
+ }
+
+- inline bool contains(insn_info const & o) const {
++ inline bool
++ contains (insn_info const & o) const
++ {
+ if (o._def & ~_def)
+ return false;
+ if (o._use & ~_use)
+@@ -211,21 +212,22 @@ clear (void)
+ infos.clear ();
+ }
+
+-static bool is_reg_dead(unsigned regno, unsigned pos)
++static bool
++is_reg_dead (unsigned regno, unsigned pos)
+ {
+- if (pos >= infos.size())
++ if (pos >= infos.size ())
+ return true;
+
+ insn_info & ii0 = infos[pos++];
+- if (!ii0.is_use(regno))
++ if (!ii0.is_use (regno))
+ return true;
+
+- if (pos >= infos.size())
++ if (pos >= infos.size ())
+ return true;
+
+ insn_info & ii1 = infos[pos];
+
+- return !ii1.is_use(regno);
++ return !ii1.is_use (regno);
+ }
+
+ /*
+@@ -274,7 +276,6 @@ update_meta_data ()
+
+ if (NONJUMP_INSN_P (insn) || LABEL_P(insn) || JUMP_P(insn) || CALL_P(insn))
+ {
+- // debug_rtx (insn);
+ if (JUMP_P(insn))
+ jumps.push_back (insn);
+
+@@ -306,7 +307,7 @@ update_meta_data ()
+ {
+ rtx_insn * insn = insns[pos];
+
+- if (pass && infos[pos].contains(ii))
++ if (pass && infos[pos].contains (ii))
+ break;
+
+ ii |= infos[pos];
+@@ -578,7 +579,6 @@ propagate_moves ()
+ {
+ std::vector<rtx_insn *>::iterator label_iter = jump_out.begin ();
+ int fixup = 0;
+- fprintf (stderr, ": need %d jump out fixups\n", jump_out.size ());
+
+ for (unsigned k = *i + 1; k != *j; ++k)
+ {
+@@ -651,7 +651,8 @@ propagate_moves ()
+ rtx_insn * after = insns[index + 1];
+ rtx bset = single_set (before);
+
+- fprintf (stderr, ": condition met, moving regs %d, %d\n", REGNO(srci), REGNO(dsti));
++ fprintf (stderr, ":bbb: propagate_moves condition met, moving regs %d, %d\n",
++ REGNO(srci), REGNO(dsti));
+
+ /* Move in front of loop and mark as dead. */
+ remove_insn (ii);
+@@ -684,7 +685,7 @@ propagate_moves ()
+ /* add fixes if there were jumps out of the loop. */
+ if (jump_out.size ())
+ {
+- fprintf (stderr, ": fixing %d jump outs\n", jump_out.size ());
++ fprintf (stderr, ":bbb: propagate_moves fixing %d jump outs\n", jump_out.size ());
+
+ for (unsigned k = 0; k < jump_out.size (); ++k)
+ {
+@@ -763,7 +764,7 @@ opt_strcpy ()
+ SET_SRC(single_set(reg2x)) = SET_SRC(single_set (x2reg));
+ insn_code_number = recog (PATTERN (reg2x), reg2x, &num_clobbers_to_add);
+
+- if (insn_code_number < 0)
++ if (insn_code_number < 0 || !check_asm_operands (reg2x))
+ {
+ /* restore register. */
+ SET_SRC(single_set(reg2x)) = SET_DEST(single_set (x2reg));
+@@ -775,7 +776,8 @@ opt_strcpy ()
+
+ fprintf (
+ stderr,
+- ": condition met, removing compare and joining insns - omit reg %d\n", REGNO(dst));
++ ":bbb: opt_strcpy condition met, removing compare and joining insns - omit reg %d\n",
++ REGNO(dst));
+
+ for (link = REG_NOTES(x2reg); link; link = XEXP(link, 1))
+ if (REG_NOTE_KIND (link) != REG_LABEL_OPERAND)
+@@ -930,14 +932,6 @@ commute_add_move (void)
+ if (!REG_P(memreg) || REGNO(memreg) != REGNO(reg1src))
+ continue;
+
+- int oldcost1 = insn_rtx_cost (set, true);
+- int oldcost2 = insn_rtx_cost (set2, true);
+-
+- fprintf (stderr, ": commute_add_move found, old cost: %d = %d + %d\n", oldcost1 + oldcost2, oldcost1, oldcost2);
+-
+- debug_rtx (insn);
+- debug_rtx (next);
+-
+ rtx pinc = gen_rtx_POST_INC(GET_MODE(dst), reg1dst);
+ rtx newmem = replace_equiv_address_nv (dst, pinc);
+
+@@ -949,14 +943,7 @@ commute_add_move (void)
+
+ add_reg_note (next, REG_INC, reg1dst);
+
+- int newcost1 = insn_rtx_cost (set, true);
+- int newcost2 = insn_rtx_cost (set2, true);
+-
+- fprintf (stderr, ": commute_add_move found, new cost: %d = %d + %d\n", newcost1 + newcost2, newcost1,
+- newcost2);
+-
+- debug_rtx (insn);
+- debug_rtx (next);
++ fprintf (stderr, ":bbb: commute_add_move found\n");
+
+ df_insn_rescan (insn);
+ df_insn_rescan (next);
+@@ -1018,11 +1005,15 @@ const_cmp_to_sub (void)
+ // if (!find_reg_note (insn, REG_DEAD, left) || !find_reg_note (insn, REG_DEAD, right))
+ // continue;
+
+- if (!is_reg_dead(REGNO(left), index) || !is_reg_dead(REGNO(right), index))
+- continue;
++ // TODO
++ // FEATURE: check if the next uses are also a add/sub
++ // then maybe that add/sub can be adjusted too
+
+- fprintf (stderr, ": found reg-reg compare with both dead: %d %d\n",
+- is_reg_dead(REGNO(left), index), is_reg_dead(REGNO(right), index));
++ if (!is_reg_dead (REGNO(left), index) || !is_reg_dead (REGNO(right), index))
++ continue;
++
++ fprintf (stderr, ":bbb: found reg-reg compare with both dead: %d %d\n", is_reg_dead (REGNO(left), index),
++ is_reg_dead (REGNO(right), index));
+
+ // maybe add a search?
+ rtx_insn * prev = insns[index - 1];
+@@ -1051,6 +1042,8 @@ const_cmp_to_sub (void)
+
+ int num_clobbers_to_add = 0;
+ int insn_code_number = recog (PATTERN (prev), prev, &num_clobbers_to_add);
++ if (insn_code_number >= 0 && !check_asm_operands (prev))
++ insn_code_number = -1;
+
+ SET_SRC(setp) = srcp;
+ SET_DEST(setp) = dstp;
+@@ -1058,9 +1051,6 @@ const_cmp_to_sub (void)
+ if (insn_code_number < 0)
+ continue;
+
+- debug_rtx (prev);
+- debug_rtx (insn);
+-
+ // also convert current statement to cmp #0, reg
+ SET_INSN_DELETED(insn);
+ rtx neu = gen_rtx_SET(cc0_rtx, gen_rtx_COMPARE(mode, reg, gen_rtx_CONST_INT(mode, 0)));
+@@ -1076,16 +1066,14 @@ const_cmp_to_sub (void)
+ // if (!(df->hard_regs_live_count[omitted_regno] -= 2))
+ // df_set_regs_ever_live (omitted_regno, false);
+
+- fprintf (stderr, ": replaced reg-reg compare with sub\n");
+- debug_rtx (prev);
+- debug_rtx (insn);
++ fprintf (stderr, ":bbb: const_cmp_to_sub replaced reg-reg compare with sub\n");
+
+ if (dstp != left)
+ {
+ // invert all conditions using this statement.
+ std::vector<unsigned> todo;
+ std::vector<unsigned> done;
+- done.resize(insns.size());
++ done.resize (insns.size ());
+ todo.push_back (index + 1);
+
+ while (todo.size ())
+@@ -1139,7 +1127,7 @@ const_cmp_to_sub (void)
+
+ if (code != newcode)
+ {
+- fprintf (stderr, ": patch jcc %d -> %d\n", code, newcode);
++ fprintf (stderr, ":bbb: patch jcc %d -> %d\n", code, newcode);
+ XEXP(jmpsrc, 0) = gen_rtx_fmt_ee(newcode, VOIDmode, XEXP(condition, 0), XEXP(condition, 1));
+ }
+ }
+@@ -1173,8 +1161,7 @@ elim_dead_assign (void)
+
+ if (!infos[index].is_use (REGNO(dst)))
+ {
+- fprintf (stderr, ": eliminate dead assignment to %d:", REGNO(dst));
+- debug_rtx (insn);
++ fprintf (stderr, ":bbb: elim_dead_assign to %d\n", REGNO(dst));
+ SET_INSN_DELETED(insn);
+ ++change_count;
+ }
+@@ -1182,6 +1169,86 @@ elim_dead_assign (void)
+ return change_count;
+ }
+
++/*
++ * rare and only little gain - but :-)
++ lea (-1,a0),a1
++ add.l d1,a1
++ subq.l #1,d1
++ ->
++ move.l a0,a1
++ subq.l #1,d1
++ add.l d1,a1
++ */
++static unsigned
++merge_add (void)
++{
++ unsigned change_count = 0;
++ for (unsigned index = 0; index + 2 < insns.size (); ++index)
++ {
++ rtx_insn * ins1 = insns[index];
++ rtx_insn * ins2 = insns[index + 1];
++ rtx_insn * ins3 = insns[index + 2];
++ if (!NONJUMP_INSN_P(ins1) && !NONJUMP_INSN_P(ins2) && !NONJUMP_INSN_P(ins3))
++ continue;
++
++ rtx set1 = single_set (ins1);
++ rtx set2 = single_set (ins2);
++ rtx set3 = single_set (ins3);
++ if (!set1 || !set2 || !set3)
++ continue;
++
++ rtx dst1 = SET_DEST(set1);
++ rtx dst2 = SET_DEST(set2);
++ rtx dst3 = SET_DEST(set3);
++ if (!REG_P(dst1) || !REG_P(dst2) || !REG_P(dst3))
++ continue;
++
++ CC_STATUS_INIT;
++ NOTICE_UPDATE_CC(PATTERN (ins2), ins2);
++ if (cc_status.value1 || cc_status.value2)
++ continue;
++
++ rtx src1 = SET_SRC(set1);
++ rtx src2 = SET_SRC(set2);
++ rtx src3 = SET_SRC(set3);
++ if (GET_CODE(src1) != PLUS || GET_CODE(src2) != PLUS || GET_CODE(src3) != PLUS)
++ continue;
++
++ rtx l1 = XEXP(src1, 0);
++ rtx l2 = XEXP(src2, 0);
++ rtx l3 = XEXP(src3, 0);
++
++ rtx r1 = XEXP(src1, 1);
++ rtx r2 = XEXP(src2, 1);
++ rtx r3 = XEXP(src3, 1);
++ if (!CONST_INT_P(r1) || !REG_P(r2) || !CONST_INT_P(r3))
++ continue;
++
++ if (REGNO(dst1) != REGNO(dst2) || REGNO(r2) != REGNO(dst3))
++ continue;
++
++ fprintf (stderr, ": merge_add pattern found\n");
++
++ SET_SRC(set1) = l1;
++ remove_insn (ins2);
++ add_insn_after (ins2, ins3, 0);
++ }
++ return change_count;
++}
++
++/*
++ * Always prefer lower register numbers within the class.
++ */
++static unsigned
++bb_reg_rename(void)
++{
++ unsigned change_count = 0;
++ for (unsigned index = 0; index < insns.size (); ++index)
++ {
++ }
++ return change_count;
++}
++
+ /* Main entry point to the pass. */
+ static unsigned int
+ execute_bbb_optimizations (void)
+@@ -1195,22 +1262,31 @@ execute_bbb_optimizations (void)
+ for (;;)
+ {
+ int done = 1;
+- if (propagate_moves ())
+- done = 0, update_meta_data ();
++ for (;;)
++ {
++ if (propagate_moves ())
++ done = 0, update_meta_data ();
+
+- if (offset_2_autoinc ())
+- done = 0, update_meta_data ();
++ if (offset_2_autoinc ())
++ done = 0, update_meta_data ();
+
+- if (opt_strcpy ())
+- done = 0, update_meta_data ();
++ if (opt_strcpy ())
++ done = 0, update_meta_data ();
+
+- if (commute_add_move ())
+- done = 0, update_meta_data ();
++ if (commute_add_move ())
++ done = 0, update_meta_data ();
+
+- if (const_cmp_to_sub ())
+- done = 0, update_meta_data ();
++ if (const_cmp_to_sub ())
++ done = 0, update_meta_data ();
++
++ if (merge_add ())
++ done = 0, update_meta_data ();
++
++ if (elim_dead_assign ())
++ done = 0, update_meta_data ();
++ }
+
+- if (elim_dead_assign ())
++ if (bb_reg_rename ())
+ done = 0, update_meta_data ();
+
+ if (done)
+@@ -1250,7 +1326,7 @@ namespace
+ virtual bool
+ gate (function *)
+ {
+- return TARGET_AMIGA && flag_bbb_opts;
++ return TARGET_AMIGA;// && flag_bbb_opts;
+ }
+
+ virtual unsigned int
+
+From 7ea53a15d0e3f77f38f9383d8779c7755c499e4b Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 7 Apr 2017 04:07:36 +0200
+Subject: [PATCH 060/303] @B fix loop hang
+
+---
+ gcc/bbb-opts.c | 35 ++++++++++++++++-------------------
+ 1 file changed, 16 insertions(+), 19 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index d9e77c53856d..c525ae432071 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -1240,7 +1240,7 @@ merge_add (void)
+ * Always prefer lower register numbers within the class.
+ */
+ static unsigned
+-bb_reg_rename(void)
++bb_reg_rename (void)
+ {
+ unsigned change_count = 0;
+ for (unsigned index = 0; index < insns.size (); ++index)
+@@ -1262,29 +1262,26 @@ execute_bbb_optimizations (void)
+ for (;;)
+ {
+ int done = 1;
+- for (;;)
+- {
+- if (propagate_moves ())
+- done = 0, update_meta_data ();
++ if (propagate_moves ())
++ done = 0, update_meta_data ();
+
+- if (offset_2_autoinc ())
+- done = 0, update_meta_data ();
++ if (offset_2_autoinc ())
++ done = 0, update_meta_data ();
+
+- if (opt_strcpy ())
+- done = 0, update_meta_data ();
++ if (opt_strcpy ())
++ done = 0, update_meta_data ();
+
+- if (commute_add_move ())
+- done = 0, update_meta_data ();
++ if (commute_add_move ())
++ done = 0, update_meta_data ();
+
+- if (const_cmp_to_sub ())
+- done = 0, update_meta_data ();
++ if (const_cmp_to_sub ())
++ done = 0, update_meta_data ();
+
+- if (merge_add ())
+- done = 0, update_meta_data ();
++ if (merge_add ())
++ done = 0, update_meta_data ();
+
+- if (elim_dead_assign ())
+- done = 0, update_meta_data ();
+- }
++ if (elim_dead_assign ())
++ done = 0, update_meta_data ();
+
+ if (bb_reg_rename ())
+ done = 0, update_meta_data ();
+@@ -1326,7 +1323,7 @@ namespace
+ virtual bool
+ gate (function *)
+ {
+- return TARGET_AMIGA;// && flag_bbb_opts;
++ return TARGET_AMIGA; // && flag_bbb_opts;
+ }
+
+ virtual unsigned int
+
+From cf6a128caf791e74460c8f312e624be2ab373b4e Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sat, 8 Apr 2017 17:06:18 +0200
+Subject: [PATCH 061/303] @N add option letters to -fbbb
+
+---
+ gcc/config/m68k/amigaos.opt | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt
+index 2d8bed0a9103..a5a14449dea9 100644
+--- gcc/config/m68k/amigaos.opt
++++ gcc/config/m68k/amigaos.opt
+@@ -43,6 +43,6 @@ mcrt=
+ Target RejectNegative Var(amigaos_crt) Joined
+ Specify startup binary
+
+-fbbb
+-Target Var(flag_bbb_opts,1) UInteger Init(0)
++fbbb=
++Target Var(flag_bbb_opts) Joined
+ Enable Bebbo's optimizations
+
+From 477bce8c47781fce8d11797829a3bd6ade798273 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sat, 8 Apr 2017 17:07:04 +0200
+Subject: [PATCH 062/303] @B some fixes, also invoke regrename directly, @R use
+ letter from -fbbb=
+
+---
+ gcc/bbb-opts.c | 347 ++++++++++++++++++++++++++++++++++++++++----------------
+ gcc/regrename.c | 12 +-
+ 2 files changed, 260 insertions(+), 99 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index c525ae432071..737a5c00af3b 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -45,6 +45,7 @@
+ #include "emit-rtl.h"
+ #include "tree-pass.h"
+ #include "conditions.h"
++#include "cselib.h"
+ #include <vector>
+ #include <map>
+
+@@ -110,14 +111,14 @@ struct insn_info
+ return t;
+ }
+
+- inline insn_info
+- operator & (insn_info const & o) const
+- {
+- insn_info t;
+- t._use = _use & o._use;
+- t._def = _def & o._def;
+- return t;
+- }
++// inline insn_info
++// operator & (insn_info const & o) const
++// {
++// insn_info t;
++// t._use = _use & o._use;
++// t._def = _def & o._def;
++// return t;
++// }
+
+ inline insn_info &
+ operator |= (insn_info const & o)
+@@ -130,7 +131,7 @@ struct insn_info
+ inline insn_info &
+ operator &= (insn_info const & o)
+ {
+- _use &= o._use;
++ _use &= o._use & o._def;
+ _def &= o._def;
+ return *this;
+ }
+@@ -162,6 +163,18 @@ struct insn_info
+
+ void
+ scan (rtx);
++
++ unsigned
++ get_def_mask () const
++ {
++ if (!_def || _def > 0xffff)
++ return 0;
++
++ unsigned mask = _def - 1;
++ if (_def > 0xff)
++ mask &= 0xff00;
++ return mask;
++ }
+ };
+
+ /* scan rtx for registers and set the corresponding flags. */
+@@ -192,6 +205,47 @@ insn_info::scan (rtx x)
+ }
+ }
+
++/* perform reg renaming. */
++static void
++do_reg_rename (rtx x, unsigned oldregno, unsigned newregno)
++{
++ if (REG_P(x))
++ {
++ if (REGNO(x) == oldregno)
++ df_ref_change_reg_with_loc (x, newregno);
++ return;
++ }
++
++ if (x == cc0_rtx)
++ return;
++
++ RTX_CODE code = GET_CODE(x);
++ const char *fmt = GET_RTX_FORMAT(code);
++ for (int i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
++ {
++ if (fmt[i] == 'e')
++ do_reg_rename (XEXP(x, i), oldregno, newregno);
++ else if (fmt[i] == 'E')
++ for (int j = XVECLEN (x, i) - 1; j >= 0; j--)
++ do_reg_rename (XVECEXP(x, i, j), oldregno, newregno);
++ }
++}
++
++static int
++bit2regno (unsigned bit)
++{
++ if (!bit)
++ return -1;
++
++ unsigned regno = 0;
++ while (!(bit & 1))
++ {
++ ++regno;
++ bit >>= 1;
++ }
++ return regno;
++}
++
+ /*
+ * Collect some data.
+ */
+@@ -212,22 +266,25 @@ clear (void)
+ infos.clear ();
+ }
+
++/*
++ * return true if the register is DEAD.
++ */
+ static bool
+ is_reg_dead (unsigned regno, unsigned pos)
+ {
+- if (pos >= infos.size ())
+- return true;
+-
+- insn_info & ii0 = infos[pos++];
+- if (!ii0.is_use (regno))
+- return true;
+-
+- if (pos >= infos.size ())
+- return true;
+-
+- insn_info & ii1 = infos[pos];
++ for(;;) {
++ if (pos + 1 >= infos.size ())
++ return true;
++
++ rtx_insn * insn = insns[pos + 1];
++ if (!LABEL_P(insn) && GET_CODE(insn) != USE)
++ break;
++ ++pos;
++ }
+
+- return !ii1.is_use (regno);
++ insn_info & ii0 = infos[pos + 1];
++ // not dead if usage is reported in the next statement
++ return !ii0.is_use (regno);
+ }
+
+ /*
+@@ -242,6 +299,8 @@ dump_insns (char const * name)
+ {
+ insn_info & ii = infos[i];
+
++ fprintf(stderr, "%d: ", i);
++
+ for (int j = 0; j < 8; ++j)
+ if (ii.is_use (j))
+ fprintf (stderr, ii.is_def (j) ? "*d%d " : "d%d ", j);
+@@ -301,6 +360,9 @@ update_meta_data ()
+ std::pair<unsigned, insn_info> p = *todo.rbegin ();
+ todo.pop_back ();
+
++// fprintf(stderr, "%d ", p.first);
++// dump_insns("update");
++
+ insn_info ii = p.second;
+
+ for (int pos = p.first; pos >= 0; --pos)
+@@ -655,9 +717,8 @@ propagate_moves ()
+ REGNO(srci), REGNO(dsti));
+
+ /* Move in front of loop and mark as dead. */
+- remove_insn (ii);
+- add_insn_after (ii, before, 0);
+- add_reg_note (ii, REG_DEAD, srci);
++ rtx_insn * newii = make_insn_raw(PATTERN(ii));
++ SET_INSN_DELETED(ii);
+
+ /* Plus check if the reg was just loaded. */
+ if (bset)
+@@ -665,22 +726,31 @@ propagate_moves ()
+ rtx bdst = SET_DEST(bset);
+ if (REG_P(bdst) && REGNO(bdst) == REGNO(srci))
+ {
+- SET_DEST(bset) = dsti;
+- SET_INSN_DELETED(ii);
++ SET_SRC(PATTERN(newii)) = SET_SRC(bset);
++// SET_INSN_DELETED(ii);
+ }
+ }
++ else
++ add_reg_note (newii, REG_DEAD, srci);
++
++
++ add_insn_after (newii, before, 0);
++
+
+ /* Move behind loop - into next BB. */
+- remove_insn (jj);
+- add_insn_before (jj, after, 0);
++ rtx_insn * newjj = make_insn_raw(PATTERN(jj));
++ add_insn_before (newjj, after, 0);
++ SET_INSN_DELETED(jj);
+
+ reg_reg.erase (j);
+ reg_reg.erase (i);
+ j = reg_reg.end ();
+ inc = false;
+
+- df_insn_rescan (ii);
+- df_insn_rescan (jj);
++// df_insn_rescan (ii);
++// df_insn_rescan (jj);
++ df_insn_rescan (newii);
++ df_insn_rescan (newjj);
+
+ /* add fixes if there were jumps out of the loop. */
+ if (jump_out.size ())
+@@ -761,17 +831,11 @@ opt_strcpy ()
+ int num_clobbers_to_add = 0;
+ int insn_code_number;
+
+- SET_SRC(single_set(reg2x)) = SET_SRC(single_set (x2reg));
+- insn_code_number = recog (PATTERN (reg2x), reg2x, &num_clobbers_to_add);
+-
+- if (insn_code_number < 0 || !check_asm_operands (reg2x))
++ rtx_insn * newinsn = make_insn_raw (
++ gen_rtx_SET(SET_DEST(single_set(reg2x)), SET_SRC(single_set (x2reg))));
++ insn_code_number = recog (PATTERN (newinsn), newinsn, &num_clobbers_to_add);
++ if (insn_code_number >= 0 && check_asm_operands (PATTERN (newinsn)))
+ {
+- /* restore register. */
+- SET_SRC(single_set(reg2x)) = SET_DEST(single_set (x2reg));
+- }
+- else
+- {
+-
+ rtx link;
+
+ fprintf (
+@@ -779,6 +843,8 @@ opt_strcpy ()
+ ":bbb: opt_strcpy condition met, removing compare and joining insns - omit reg %d\n",
+ REGNO(dst));
+
++ SET_SRC(single_set(reg2x)) = SET_SRC(single_set (x2reg));
++
+ for (link = REG_NOTES(x2reg); link; link = XEXP(link, 1))
+ if (REG_NOTE_KIND (link) != REG_LABEL_OPERAND)
+ {
+@@ -935,16 +1001,20 @@ commute_add_move (void)
+ rtx pinc = gen_rtx_POST_INC(GET_MODE(dst), reg1dst);
+ rtx newmem = replace_equiv_address_nv (dst, pinc);
+
++ rtx_insn * newinsn = make_insn_raw (gen_rtx_SET(reg1dst, reg1src));
++ if (recog (PATTERN (newinsn), newinsn, 0) < 0 || !check_asm_operands (PATTERN (newinsn)))
++ continue;
++
+ if (validate_change (next, &SET_DEST(set2), newmem, 0))
+ {
++ fprintf (stderr, ":bbb: commute_add_move found\n");
++
+ SET_INSN_DELETED(insn);
+
+- insn = emit_insn_before (gen_movsi (reg1dst, reg1src), next);
++ insn = emit_insn_before (newinsn, next);
+
+ add_reg_note (next, REG_INC, reg1dst);
+
+- fprintf (stderr, ":bbb: commute_add_move found\n");
+-
+ df_insn_rescan (insn);
+ df_insn_rescan (next);
+
+@@ -1037,18 +1107,11 @@ const_cmp_to_sub (void)
+ rtx reg = dstp == left ? right : left;
+ rtx plus = gen_rtx_PLUS(mode, reg, gen_rtx_CONST_INT (mode, intval));
+
+- SET_SRC(setp) = plus;
+- SET_DEST(setp) = reg;
++ rtx_insn * neuprev = make_insn_raw (gen_rtx_SET(reg, plus));
+
+ int num_clobbers_to_add = 0;
+- int insn_code_number = recog (PATTERN (prev), prev, &num_clobbers_to_add);
+- if (insn_code_number >= 0 && !check_asm_operands (prev))
+- insn_code_number = -1;
+-
+- SET_SRC(setp) = srcp;
+- SET_DEST(setp) = dstp;
+-
+- if (insn_code_number < 0)
++ int insn_code_number = recog (PATTERN (neuprev), neuprev, &num_clobbers_to_add);
++ if (insn_code_number >= 0 && !check_asm_operands (PATTERN (neuprev)))
+ continue;
+
+ // also convert current statement to cmp #0, reg
+@@ -1058,11 +1121,11 @@ const_cmp_to_sub (void)
+ add_reg_note (insn, REG_DEAD, reg);
+
+ SET_INSN_DELETED(prev);
+- neu = gen_rtx_SET(reg, plus);
+- prev = emit_insn_before (neu, insn);
++ prev = emit_insn_before (neuprev, insn);
+
+ // urks - unknown side effects
+ // int omitted_regno = REGNO(dstp);
++// cselib_invalidate_rtx (dstp);
+ // if (!(df->hard_regs_live_count[omitted_regno] -= 2))
+ // df_set_regs_ever_live (omitted_regno, false);
+
+@@ -1159,7 +1222,7 @@ elim_dead_assign (void)
+ if (!REG_P(dst) || !REG_P(src))
+ continue;
+
+- if (!infos[index].is_use (REGNO(dst)))
++ if (is_reg_dead(REGNO(dst),index))
+ {
+ fprintf (stderr, ":bbb: elim_dead_assign to %d\n", REGNO(dst));
+ SET_INSN_DELETED(insn);
+@@ -1227,7 +1290,7 @@ merge_add (void)
+ if (REGNO(dst1) != REGNO(dst2) || REGNO(r2) != REGNO(dst3))
+ continue;
+
+- fprintf (stderr, ": merge_add pattern found\n");
++ fprintf (stderr, ":bbb: merge_add applied\n");
+
+ SET_SRC(set1) = l1;
+ remove_insn (ins2);
+@@ -1242,60 +1305,82 @@ merge_add (void)
+ static unsigned
+ bb_reg_rename (void)
+ {
+- unsigned change_count = 0;
++ dump_insns("bb_reg_rename");
+ for (unsigned index = 0; index < insns.size (); ++index)
+ {
+- }
+- return change_count;
+-}
++ insn_info & ii = infos[index];
++ const unsigned def = ii._def;
++ unsigned mask = ii.get_def_mask ();
+
+-/* Main entry point to the pass. */
+-static unsigned int
+-execute_bbb_optimizations (void)
+-{
+- df_set_flags (DF_LR_RUN_DCE + DF_DEFER_INSN_RESCAN);
+- df_note_add_problem ();
+- df_analyze ();
++ if (!mask)
++ continue;
+
+- update_meta_data ();
++ std::vector<unsigned> found;
++ std::vector<unsigned> todo;
++ if (index + 1 < insns.size ())
++ todo.push_back (index + 1);
+
+- for (;;)
+- {
+- int done = 1;
+- if (propagate_moves ())
+- done = 0, update_meta_data ();
++ found.push_back (index);
++ /* a register was defined, follow all branches. */
++ while (todo.size ())
++ {
++ unsigned pos = todo[todo.size () - 1];
++ todo.pop_back ();
+
+- if (offset_2_autoinc ())
+- done = 0, update_meta_data ();
++ insn_info & jj = infos[pos];
++ /* defined again. */
++ if (jj._def & def)
++ continue;
+
+- if (opt_strcpy ())
+- done = 0, update_meta_data ();
++ /* not referenced. */
++ if (!(jj._use & def))
++ continue;
+
+- if (commute_add_move ())
+- done = 0, update_meta_data ();
++ /* update free regs. */
++ mask &= ~jj._use;
++ if (!mask)
++ break;
+
+- if (const_cmp_to_sub ())
+- done = 0, update_meta_data ();
++ found.push_back (pos);
+
+- if (merge_add ())
+- done = 0, update_meta_data ();
++ /* follow jump and/or next insn. */
++ rtx_insn * insn = insns[index];
++ if (JUMP_P(insn))
++ {
++ std::map<rtx_insn *, unsigned>::iterator j = insn2index.find ((rtx_insn *) JUMP_LABEL(insn));
++ if (j != insn2index.end ())
++ todo.push_back (j->second);
+
+- if (elim_dead_assign ())
+- done = 0, update_meta_data ();
++ rtx jmppattern = PATTERN (insn);
+
+- if (bb_reg_rename ())
+- done = 0, update_meta_data ();
++ rtx jmpsrc = XEXP(jmppattern, 1);
++ if (GET_CODE(jmpsrc) == IF_THEN_ELSE)
++ if (pos + 1 < insns.size ())
++ todo.push_back (pos + 1);
++ }
++ else if (pos + 1 < insns.size ())
++ todo.push_back (pos + 1);
++ }
+
+- if (done)
+- break;
+- }
++ if (mask)
++ {
++ int oldregno = bit2regno (def);
++ int newregno = bit2regno (mask);
++ fprintf (stderr, ":bbb: bb_reg_rename %d -> %d\n", oldregno, newregno);
+
+-// dump_insns ("bbb 1");
+- clear ();
++ for (std::vector<unsigned>::iterator i = found.begin (); i != found.end (); ++i)
++ do_reg_rename (PATTERN (insns[*i]), oldregno, newregno);
+
++ cselib_invalidate_rtx (gen_raw_REG (SImode, oldregno));
++ cselib_invalidate_rtx (gen_raw_REG (SImode, newregno));
++ return 1;
++ }
++ }
+ return 0;
+ }
+
++extern class opt_pass * global_pass_regrename;
++
+ namespace
+ {
+
+@@ -1315,7 +1400,7 @@ namespace
+ {
+ public:
+ pass_bbb_optimizations (gcc::context *ctxt) :
+- rtl_opt_pass (pass_data_bbb_optimizations, ctxt)
++ rtl_opt_pass (pass_data_bbb_optimizations, ctxt), pp (0)
+ {
+ }
+
+@@ -1323,7 +1408,7 @@ namespace
+ virtual bool
+ gate (function *)
+ {
+- return TARGET_AMIGA; // && flag_bbb_opts;
++ return TARGET_AMIGA && flag_bbb_opts;
+ }
+
+ virtual unsigned int
+@@ -1335,13 +1420,81 @@ namespace
+ opt_pass *
+ clone ()
+ {
+- return new pass_bbb_optimizations (m_ctxt);
++ pass_bbb_optimizations * bbb = new pass_bbb_optimizations (m_ctxt);
++ // bbb->pp = pp + 1;
++ return bbb;
+ }
+
++ unsigned int pp;
++
++ unsigned
++ execute_bbb_optimizations (void);
+ };
+ // class pass_bbb_optimizations
+
+-}// anon namespace
++
++ /* Main entry point to the pass. */
++ unsigned
++ pass_bbb_optimizations::execute_bbb_optimizations (void)
++ {
++ df_set_flags (DF_LR_RUN_DCE + DF_DEFER_INSN_RESCAN);
++ df_note_add_problem ();
++ df_analyze ();
++
++ update_meta_data ();
++
++ bool do_opt_strcpy = strchr(flag_bbb_opts, 's') || strchr(flag_bbb_opts, '*');
++ bool do_commute_add_move = strchr(flag_bbb_opts, 'a') || strchr(flag_bbb_opts, '*');
++ bool do_propagate_moves = strchr(flag_bbb_opts, 'p') || strchr(flag_bbb_opts, '*');
++ bool do_const_cmp_to_sub = strchr(flag_bbb_opts, 'c') || strchr(flag_bbb_opts, '*');
++ bool do_merge_add = strchr(flag_bbb_opts, 'm') || strchr(flag_bbb_opts, '*');
++ bool do_elim_dead_assign = strchr(flag_bbb_opts, 'e') || strchr(flag_bbb_opts, '*');
++ bool do_bb_reg_rename = strchr(flag_bbb_opts, 'r') || strchr(flag_bbb_opts, '*');
++
++
++ for (;;)
++ {
++ int done = 1;
++ if (do_opt_strcpy && opt_strcpy ())
++ done = 0, update_meta_data ();
++
++ if (do_commute_add_move && commute_add_move ())
++ done = 0, update_meta_data ();
++
++ if (do_propagate_moves && propagate_moves ())
++ done = 0, update_meta_data ();
++
++// if (offset_2_autoinc ())
++// done = 0, update_meta_data ();
++
++ if (do_const_cmp_to_sub && const_cmp_to_sub ())
++ done = 0, update_meta_data ();
++
++ if (do_merge_add && merge_add ())
++ done = 0, update_meta_data ();
++
++ if (do_elim_dead_assign && elim_dead_assign ())
++ done = 0, update_meta_data ();
++
++// if (do_bb_reg_rename && bb_reg_rename ())
++// done = 0, update_meta_data ();
++ if (done)
++ break;
++ }
++
++ if (do_bb_reg_rename && ::global_pass_regrename)
++ {
++ class opt_pass * rr = ::global_pass_regrename->clone();
++ rr->execute(0);
++ }
++
++ if (strchr(flag_bbb_opts, 'X')) dump_insns ("bbb 1");
++ clear ();
++
++ return 0;
++ }
++
++} // anon namespace
+
+ rtl_opt_pass *
+ make_pass_bbb_optimizations (gcc::context * ctxt)
+diff --git a/gcc/regrename.c b/gcc/regrename.c
+index 4ba825e8d8e8..696e5557780e 100755
+--- gcc/regrename.c
++++ gcc/regrename.c
+@@ -1913,6 +1913,8 @@ regrename_optimize (void)
+ return 0;
+ }
+
++class opt_pass * global_pass_regrename;
++
+ namespace {
+
+ const pass_data pass_data_regrename =
+@@ -1927,13 +1929,14 @@ const pass_data pass_data_regrename =
+ 0, /* todo_flags_start */
+ TODO_df_finish, /* todo_flags_finish */
+ };
+-
+ class pass_regrename : public rtl_opt_pass
+ {
+ public:
+ pass_regrename (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_regrename, ctxt)
+- {}
++ {
++ ::global_pass_regrename = this;
++ }
+
+ /* opt_pass methods: */
+ virtual bool gate (function *)
+@@ -1943,6 +1946,11 @@ class pass_regrename : public rtl_opt_pass
+
+ virtual unsigned int execute (function *) { return regrename_optimize (); }
+
++ opt_pass * clone ()
++ {
++ return new pass_regrename(m_ctxt);
++ }
++
+ }; // class pass_regrename
+
+ } // anon namespace
+
+From b747a5666a06f73ae8628788246f6d9e614f6393 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 10 Apr 2017 10:46:07 +0200
+Subject: [PATCH 063/303] @B shrink_stack_frame starts working
+
+---
+ gcc/bbb-opts.c | 583 ++++++++++++++++++++++++++++++++++++++++++---------------
+ gcc/passes.def | 1 -
+ 2 files changed, 427 insertions(+), 157 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 737a5c00af3b..6114e2fa5ed0 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -111,15 +111,6 @@ struct insn_info
+ return t;
+ }
+
+-// inline insn_info
+-// operator & (insn_info const & o) const
+-// {
+-// insn_info t;
+-// t._use = _use & o._use;
+-// t._def = _def & o._def;
+-// return t;
+-// }
+-
+ inline insn_info &
+ operator |= (insn_info const & o)
+ {
+@@ -250,6 +241,7 @@ bit2regno (unsigned bit)
+ * Collect some data.
+ */
+ static std::vector<rtx_insn *> insns;
++static std::vector<rtx_insn *> temp;
+ static std::vector<rtx_insn *> jumps;
+ static std::map<rtx_insn *, unsigned> insn2index;
+ static std::vector<insn_info> infos;
+@@ -272,15 +264,16 @@ clear (void)
+ static bool
+ is_reg_dead (unsigned regno, unsigned pos)
+ {
+- for(;;) {
+- if (pos + 1 >= infos.size ())
+- return true;
+-
+- rtx_insn * insn = insns[pos + 1];
+- if (!LABEL_P(insn) && GET_CODE(insn) != USE)
+- break;
+- ++pos;
+- }
++ for (;;)
++ {
++ if (pos + 1 >= infos.size ())
++ return true;
++
++ rtx_insn * insn = insns[pos + 1];
++ if (!LABEL_P(insn) && GET_CODE(insn) != USE)
++ break;
++ ++pos;
++ }
+
+ insn_info & ii0 = infos[pos + 1];
+ // not dead if usage is reported in the next statement
+@@ -292,14 +285,19 @@ is_reg_dead (unsigned regno, unsigned pos)
+ * Sometimes used during debugging.
+ */
+ static void
+-dump_insns (char const * name)
++dump_insns (char const * name, bool all)
+ {
+ fprintf (stderr, "====================================: %s\n", name);
++ if (all)
++ {
++ for (rtx_insn * insn = get_insns (); insn && insn != insns[0]; insn = NEXT_INSN (insn))
++ debug_rtx (insn);
++ }
+ for (unsigned i = 0; i < insns.size (); ++i)
+ {
+ insn_info & ii = infos[i];
+
+- fprintf(stderr, "%d: ", i);
++ fprintf (stderr, "%d: ", i);
+
+ for (int j = 0; j < 8; ++j)
+ if (ii.is_use (j))
+@@ -314,6 +312,13 @@ dump_insns (char const * name)
+
+ fprintf (stderr, "\t");
+ debug_rtx (insns[i]);
++
++ if (all)
++ {
++ rtx_insn * p = i + 1 < insns.size () ? insns[i + 1] : 0;
++ for (rtx_insn * q = NEXT_INSN (insns[i]); q && q != p; q = NEXT_INSN (q))
++ debug_rtx (q);
++ }
+ }
+ }
+
+@@ -321,7 +326,7 @@ dump_insns (char const * name)
+ * Create a filtered view of insns - keep only those to work with.
+ */
+ static void
+-update_meta_data ()
++update_insns ()
+ {
+ rtx_insn *insn, *next;
+ clear ();
+@@ -342,7 +347,11 @@ update_meta_data ()
+ insns.push_back (insn);
+ }
+ }
++}
+
++static void
++update_insn_infos (void)
++{
+ /* prepare insn_info */
+ insn_info ii;
+ for (unsigned i = 0; i < insns.size (); ++i)
+@@ -360,14 +369,13 @@ update_meta_data ()
+ std::pair<unsigned, insn_info> p = *todo.rbegin ();
+ todo.pop_back ();
+
+-// fprintf(stderr, "%d ", p.first);
+-// dump_insns("update");
+-
+ insn_info ii = p.second;
+
+ for (int pos = p.first; pos >= 0; --pos)
+ {
+ rtx_insn * insn = insns[pos];
++ if (!insn) // moved to temp for stack frame cleanup
++ continue;
+
+ if (pass && infos[pos].contains (ii))
+ break;
+@@ -487,7 +495,6 @@ update_meta_data ()
+ }
+ ++pass;
+ }
+-
+ }
+
+ /*
+@@ -717,7 +724,7 @@ propagate_moves ()
+ REGNO(srci), REGNO(dsti));
+
+ /* Move in front of loop and mark as dead. */
+- rtx_insn * newii = make_insn_raw(PATTERN(ii));
++ rtx_insn * newii = make_insn_raw (PATTERN (ii));
+ SET_INSN_DELETED(ii);
+
+ /* Plus check if the reg was just loaded. */
+@@ -733,12 +740,10 @@ propagate_moves ()
+ else
+ add_reg_note (newii, REG_DEAD, srci);
+
+-
+ add_insn_after (newii, before, 0);
+
+-
+ /* Move behind loop - into next BB. */
+- rtx_insn * newjj = make_insn_raw(PATTERN(jj));
++ rtx_insn * newjj = make_insn_raw (PATTERN (jj));
+ add_insn_before (newjj, after, 0);
+ SET_INSN_DELETED(jj);
+
+@@ -895,47 +900,6 @@ opt_strcpy ()
+ return change_count;
+ }
+
+-/*
+- * Convert loops using a counting reg as offset with an address reg
+- * into a loop with auto inc address regs.
+- */
+-static unsigned
+-offset_2_autoinc (void)
+-{
+- unsigned change_count = 0;
+-#if 0
+- rtx_insn * reg_const = 0;
+-
+- for (unsigned index = 0; index < insns.size (); ++index)
+- {
+- rtx_insn * insn = insns[index];
+-
+- if (!next || !LABEL_P(next) || LABEL_NUSES(next) != 1)
+- continue;
+-
+- if (!NONJUMP_INSN_P(insn))
+- continue;
+-
+- rtx use = single_set (insn);
+- if (!use)
+- continue;
+-
+- rtx reg = SET_DEST(use);
+- if (!REG_P(reg))
+- continue;
+-
+- rtx val = SET_SRC(use);
+-
+-// fprintf(stderr, "possible start for offset_2_autoinc\n");
+-// //debug_rtx(insn);
+-// //debug_rtx(next);
+-
+- }
+-
+-#endif
+- return change_count;
+-}
+-
+ /*
+ * convert
+ *
+@@ -1052,7 +1016,7 @@ const_cmp_to_sub (void)
+ {
+ unsigned change_count = 0;
+ #if HAVE_cc0
+- for (unsigned index = 1; index + 1 < insns.size (); ++index)
++ for (unsigned index = insns.size () - 2; index > 0; --index)
+ {
+ rtx_insn * insn = insns[index];
+ rtx seti = single_set (insn);
+@@ -1072,13 +1036,13 @@ const_cmp_to_sub (void)
+ if (!REG_P(left) || !REG_P(right))
+ continue;
+
+-// if (!find_reg_note (insn, REG_DEAD, left) || !find_reg_note (insn, REG_DEAD, right))
+-// continue;
+-
+ // TODO
+ // FEATURE: check if the next uses are also a add/sub
+ // then maybe that add/sub can be adjusted too
+
++ // if (!find_reg_note (insn, REG_DEAD, left) || !find_reg_note (insn, REG_DEAD, right))
++ // continue;
++ // use own reg_dead
+ if (!is_reg_dead (REGNO(left), index) || !is_reg_dead (REGNO(right), index))
+ continue;
+
+@@ -1222,7 +1186,7 @@ elim_dead_assign (void)
+ if (!REG_P(dst) || !REG_P(src))
+ continue;
+
+- if (is_reg_dead(REGNO(dst),index))
++ if (is_reg_dead (REGNO(dst), index))
+ {
+ fprintf (stderr, ":bbb: elim_dead_assign to %d\n", REGNO(dst));
+ SET_INSN_DELETED(insn);
+@@ -1278,8 +1242,8 @@ merge_add (void)
+ continue;
+
+ rtx l1 = XEXP(src1, 0);
+- rtx l2 = XEXP(src2, 0);
+- rtx l3 = XEXP(src3, 0);
++// rtx l2 = XEXP(src2, 0);
++// rtx l3 = XEXP(src3, 0);
+
+ rtx r1 = XEXP(src1, 1);
+ rtx r2 = XEXP(src2, 1);
+@@ -1293,89 +1257,393 @@ merge_add (void)
+ fprintf (stderr, ":bbb: merge_add applied\n");
+
+ SET_SRC(set1) = l1;
+- remove_insn (ins2);
+- add_insn_after (ins2, ins3, 0);
++ rtx_insn * newins2 = make_insn_raw (PATTERN (ins2));
++ add_insn_after (newins2, ins3, 0);
++ SET_INSN_DELETED(ins2);
++ df_insn_rescan (ins1);
+ }
+ return change_count;
+ }
+
+-/*
+- * Always prefer lower register numbers within the class.
++static void
++clear_temp ()
++{
++ for (unsigned i = 0; i < temp.size (); ++i)
++ if (temp[i])
++ insns[i] = temp[i], temp[i] = 0;
++}
++
++/**
++ * 1. scan for all used registers.
++ * 2. scan the stack from for omittable push/pop
++ * 3. adjust stack frame + insns referring to stack pointer
++ * typical code:
++ subq.l #4,sp
++ movem.l #16190,-(sp)
++ move.l 52(sp),d2
++ move.l 56(sp),d3
++
++ * or
++ link a5,#4
++ movem.l #16190,-(sp)
++ move.l 8(a5),d2
++ move.l 12(a5),d3
++ *
++ * => with a5 check only prolog/epilog
++ * => without a5 adjust insns referring sp if offset > startoffset + current sp diff
++ *
++ * startvalue count(pushes)*4
++ * newstartvalue = startvalue - omitted pushes
+ */
+ static unsigned
+-bb_reg_rename (void)
++shrink_stack_frame (void)
+ {
+- dump_insns("bb_reg_rename");
+- for (unsigned index = 0; index < insns.size (); ++index)
++ /* nothing to do. */
++ if (!insns.size ())
++ return 0;
++
++ temp.resize (insns.size ());
++
++ unsigned pos = 0;
++ rtx_insn * insn = insns[pos];
++ if (JUMP_P(insn)) /* return -> empty function*/
++ return 0;
++
++ bool usea5 = false;
++ unsigned paramstart = 4;
++ /*
++ * Move prologue to temp.
++ * Only register push and parallel insn unless its a link a5 are moved.
++ */
++ rtx_insn * prev = get_insns ();
++ for (; pos < insns.size ();)
+ {
+- insn_info & ii = infos[index];
+- const unsigned def = ii._def;
+- unsigned mask = ii.get_def_mask ();
++ insn = insns[pos];
+
+- if (!mask)
+- continue;
++ /* check for prologue end. */
++ for (; prev != insn; prev = NEXT_INSN (prev))
++ if (NOTE_P(prev) && NOTE_KIND(prev) == NOTE_INSN_PROLOGUE_END)
++ break;
++ if (prev != insn)
++ break;
++
++ rtx pattern = PATTERN (insn);
++ if (GET_CODE(pattern) == PARALLEL)
++ {
++ rtx set = XVECEXP(pattern, 0, 0);
++ rtx dst = SET_DEST(set);
++ /* ignore link a5 */
++ if (REG_P(dst) && REGNO(dst) == 13)
++ usea5 = true;
++ else
++ {
++ /* use movem */
++ temp[pos] = insn;
++ insns[pos] = 0;
++ }
++ ++pos;
++ continue;
++ }
++ if (GET_CODE(pattern) != SET)
++ {
++ ++pos;
++ continue;
++ }
++
++ /* move only the push statements. */
++ rtx src = SET_SRC(pattern);
++ rtx dest = SET_DEST(pattern);
++ if (REG_P(src))
++ {
++ if (MEM_P(dest))
++ {
++ rtx predec = XEXP(dest, 0);
++ if (GET_CODE(predec) == PRE_DEC)
++ {
++ rtx reg = XEXP(predec, 0);
++ if (REG_P(reg) && REGNO(reg) == 15)
++ {
++ temp[pos] = insn;
++ insns[pos] = 0;
++ }
++ }
++ }
++ }
++ else if (GET_CODE(src) == PLUS && REG_P(dest) && REGNO(dest) == 15)
++ {
++ /* check for stack variables. */
++ rtx reg = XEXP(src, 0);
++ rtx cx = XEXP(src, 1);
++ if (REG_P(reg) && REGNO(reg) == 15 && CONST_INT_P(cx))
++ paramstart -= INTVAL(cx);
++ }
++
++ if (++pos >= insns.size ())
++ {
++ clear_temp ();
++ return 0;
++ }
++ }
+
+- std::vector<unsigned> found;
+- std::vector<unsigned> todo;
+- if (index + 1 < insns.size ())
+- todo.push_back (index + 1);
++ if (pos == 0)
++ return 0;
++
++ unsigned prologueend = pos;
+
+- found.push_back (index);
+- /* a register was defined, follow all branches. */
+- while (todo.size ())
++ /* search epilogues - there can be multiple epilogues. */
++ while (pos < insns.size ())
++ {
++ while (pos < insns.size ())
+ {
+- unsigned pos = todo[todo.size () - 1];
+- todo.pop_back ();
++ insn = insns[pos];
++ for (; prev != insn; prev = NEXT_INSN (prev))
++ if (NOTE_P(prev) && NOTE_KIND(prev) == NOTE_INSN_EPILOGUE_BEG)
++ break;
+
+- insn_info & jj = infos[pos];
+- /* defined again. */
+- if (jj._def & def)
+- continue;
++ if (prev != insn)
++ break;
+
+- /* not referenced. */
+- if (!(jj._use & def))
+- continue;
++ ++pos;
++ }
+
+- /* update free regs. */
+- mask &= ~jj._use;
+- if (!mask)
++ /* move epilogues away. */
++ for (; pos < insns.size (); ++pos)
++ {
++ insn = insns[pos];
++ if (JUMP_P(insn)) /* return */
+ break;
+
+- found.push_back (pos);
++ if (LABEL_P(insn))
++ break;
+
+- /* follow jump and/or next insn. */
+- rtx_insn * insn = insns[index];
+- if (JUMP_P(insn))
++ /* omitt the frame pointer a5. */
++ rtx pattern = PATTERN (insn);
++ if (GET_CODE(pattern) == PARALLEL)
+ {
+- std::map<rtx_insn *, unsigned>::iterator j = insn2index.find ((rtx_insn *) JUMP_LABEL(insn));
+- if (j != insn2index.end ())
+- todo.push_back (j->second);
++ rtx set = XVECEXP(pattern, 0, 0);
++ rtx dst = SET_DEST(set);
++ /* unlink is last. */
++ if (REG_P(dst) && REGNO(dst) == 13)
++ break;
++
++ /* movem. */
++ temp[pos] = insn;
++ insns[pos] = 0;
++ }
++ else if (GET_CODE(pattern) == SET)
++ {
++ /* check for move (a7+), x */
++ rtx src = SET_SRC(pattern);
++ rtx dst = SET_DEST(pattern);
++ if (REG_P(dst))
++ {
++ if (MEM_P(src))
++ {
++ rtx postinc = XEXP(src, 0);
++ if (GET_CODE(postinc) == POST_INC)
++ {
++ rtx reg = XEXP(postinc, 0);
++ if (REG_P(reg) && REGNO(reg) == 15)
++ {
++ temp[pos] = insn;
++ insns[pos] = 0;
++ }
++ }
++ }
++ }
++ }
++ }
++ ++pos;
++ }
++ /* gather usage stats without prologue/epilogue */
++ update_insn_infos ();
++ insn_info ii;
++ for (unsigned i = 0; i < infos.size (); ++i)
++ ii |= infos[i];
++ unsigned freemask = ~ii._use;
+
+- rtx jmppattern = PATTERN (insn);
++ rtx a7 = gen_raw_REG (SImode, 15);
+
+- rtx jmpsrc = XEXP(jmppattern, 1);
+- if (GET_CODE(jmpsrc) == IF_THEN_ELSE)
+- if (pos + 1 < insns.size ())
+- todo.push_back (pos + 1);
++ unsigned adjust = 0;
++ /* now all push/pop insns are in temp. */
++ for (unsigned i = 0; i < temp.size (); ++i)
++ {
++ insn = temp[i];
++ if (!insn)
++ continue;
++
++ rtx pattern = PATTERN (insn);
++ /* check the pushed regs, either a vector or single statements */
++ if (GET_CODE(pattern) == PARALLEL)
++ {
++ std::vector<rtx> regs;
++ std::vector<rtx> clobbers;
++ for (int j = 0; j < XVECLEN(pattern, 0); ++j)
++ {
++ rtx set = XVECEXP(pattern, 0, j);
++ if (GET_CODE(set) == CLOBBER)
++ {
++ clobbers.push_back (set);
++ continue;
++ }
++ rtx src = SET_SRC(set);
++ rtx dst = SET_DEST(set);
++ rtx reg;
++ if (MEM_P(src))
++ reg = dst;
++ else if (MEM_P(dst))
++ reg = src;
++ else
++ continue;
++
++ if (i < prologueend)
++ paramstart += 4;
++ unsigned regbit = 1 << REGNO(reg);
++ if (freemask & regbit)
++ {
++ fprintf (stderr, i < prologueend ? "remove push for %d\n" : "remove pop for %d\n", REGNO(reg));
++ if (i < prologueend)
++ adjust += 4;
++ }
++ else
++ regs.push_back (reg);
++ }
++
++ /* don't touch - clobbers! */
++ if (clobbers.size())
++ continue;
++
++ if ((int) regs.size () + 1 < XVECLEN(pattern, 0) || regs.size () <= 2)
++ {
++ if (regs.size () <= 2)
++ {
++ for (unsigned k = 0; k < regs.size (); ++k)
++ {
++ rtx reg = regs[k];
++ if (i < prologueend)
++ {
++ /* push */
++ rtx dec = gen_rtx_PRE_DEC(SImode, a7);
++ rtx mem = gen_rtx_MEM (SImode, dec);
++ rtx set = gen_rtx_SET(mem, reg);
++ emit_insn_after (set, insn);
++ }
++ else
++ {
++ /* pop */
++ rtx dec = gen_rtx_POST_INC(SImode, a7);
++ rtx mem = gen_rtx_MEM (SImode, dec);
++ rtx set = gen_rtx_SET(reg, mem);
++ emit_insn_before (set, insn);
++ }
++ }
++ }
++ else
++ {
++ rtx parallel = gen_rtx_PARALLEL(VOIDmode, rtvec_alloc (regs.size () + 1));
++ int x = regs.size () * 4 + 4;
++
++ rtx plus = gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, i < prologueend ? -x : x));
++ XVECEXP(parallel, 0, 0) = gen_rtx_SET(a7, plus);
++
++ if (i >= prologueend)
++ x = 0;
++
++ for (unsigned k = 0; k < regs.size (); ++k)
++ {
++ if (i < prologueend)
++ {
++ /* push */
++ plus = gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, -x));
++ x -= 4;
++ rtx mem = gen_rtx_MEM (SImode, plus);
++ rtx set = gen_rtx_SET(mem, regs[k]);
++ XVECEXP(parallel, 0, k + 1) = set;
++ }
++ else
++ {
++ /* pop */
++ plus = x ? gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, x)) : a7;
++ x += 4;
++ rtx mem = gen_rtx_MEM (SImode, plus);
++ rtx set = gen_rtx_SET(regs[k], mem);
++ XVECEXP(parallel, 0, k + 1) = set;
++ }
++ }
++ emit_insn_after (parallel, insn);
++ }
++ SET_INSN_DELETED(insn);
++ }
++ }
++ else
++ {
++ rtx set = PATTERN (insn);
++
++ if (i < prologueend)
++ {
++ /* move x,-(a7). */
++ paramstart += 4;
++ rtx src = SET_SRC(set);
++ unsigned regbit = 1 << REGNO(src);
++ if (freemask & regbit)
++ {
++ adjust += 4;
++ fprintf (stderr, "remove push for %d\n", REGNO(src));
++ SET_INSN_DELETED(insn);
++ }
++ }
++ else
++ {
++ /* move (a7)+,x */
++ rtx dst = SET_DEST(set);
++ unsigned regbit = 1 << REGNO(dst);
++ if (freemask & regbit)
++ {
++ fprintf (stderr, "remove pop for %d\n", REGNO(dst));
++ SET_INSN_DELETED(insn);
++ }
+ }
+- else if (pos + 1 < insns.size ())
+- todo.push_back (pos + 1);
+ }
++ }
+
+- if (mask)
++ /* fix sp offsets. */
++ if (!usea5 && adjust)
++ {
++ for (unsigned index = 0; index < insns.size (); ++index)
+ {
+- int oldregno = bit2regno (def);
+- int newregno = bit2regno (mask);
+- fprintf (stderr, ":bbb: bb_reg_rename %d -> %d\n", oldregno, newregno);
++ insn = insns[index];
++ if (!insn || !INSN_P(insn))
++ continue;
+
+- for (std::vector<unsigned>::iterator i = found.begin (); i != found.end (); ++i)
+- do_reg_rename (PATTERN (insns[*i]), oldregno, newregno);
++ rtx set = single_set (insn);
++ if (!set)
++ continue;
+
+- cselib_invalidate_rtx (gen_raw_REG (SImode, oldregno));
+- cselib_invalidate_rtx (gen_raw_REG (SImode, newregno));
+- return 1;
++ rtx mem = SET_SRC(set);
++ if (MEM_P(mem))
++ {
++ rtx plus = XEXP(mem, 0);
++ if (GET_CODE(plus) == PLUS)
++ {
++ rtx sp = XEXP(plus, 0);
++ if (REG_P(sp) && REGNO(sp) == 15)
++ {
++ rtx c = XEXP(plus, 1);
++ if (CONST_INT_P(c))
++ {
++ int n = INTVAL(c);
++ if (n >= paramstart)
++ XEXP(plus, 1) = gen_rtx_CONST_INT (SImode, n - adjust);
++ }
++ }
++ }
++ }
+ }
+ }
++
++ /* restore stack insns */
++ clear_temp ();
++
+ return 0;
+ }
+
+@@ -1420,7 +1688,7 @@ namespace
+ opt_pass *
+ clone ()
+ {
+- pass_bbb_optimizations * bbb = new pass_bbb_optimizations (m_ctxt);
++ pass_bbb_optimizations * bbb = new pass_bbb_optimizations (m_ctxt);
+ // bbb->pp = pp + 1;
+ return bbb;
+ }
+@@ -1432,7 +1700,6 @@ namespace
+ };
+ // class pass_bbb_optimizations
+
+-
+ /* Main entry point to the pass. */
+ unsigned
+ pass_bbb_optimizations::execute_bbb_optimizations (void)
+@@ -1441,54 +1708,58 @@ namespace
+ df_note_add_problem ();
+ df_analyze ();
+
+- update_meta_data ();
+-
+- bool do_opt_strcpy = strchr(flag_bbb_opts, 's') || strchr(flag_bbb_opts, '*');
+- bool do_commute_add_move = strchr(flag_bbb_opts, 'a') || strchr(flag_bbb_opts, '*');
+- bool do_propagate_moves = strchr(flag_bbb_opts, 'p') || strchr(flag_bbb_opts, '*');
+- bool do_const_cmp_to_sub = strchr(flag_bbb_opts, 'c') || strchr(flag_bbb_opts, '*');
+- bool do_merge_add = strchr(flag_bbb_opts, 'm') || strchr(flag_bbb_opts, '*');
+- bool do_elim_dead_assign = strchr(flag_bbb_opts, 'e') || strchr(flag_bbb_opts, '*');
+- bool do_bb_reg_rename = strchr(flag_bbb_opts, 'r') || strchr(flag_bbb_opts, '*');
++ update_insns ();
+
++ bool do_opt_strcpy = strchr (flag_bbb_opts, 's') || strchr (flag_bbb_opts, '*');
++ bool do_commute_add_move = strchr (flag_bbb_opts, 'a') || strchr (flag_bbb_opts, '*');
++ bool do_propagate_moves = strchr (flag_bbb_opts, 'p') || strchr (flag_bbb_opts, '*');
++ bool do_const_cmp_to_sub = strchr (flag_bbb_opts, 'c') || strchr (flag_bbb_opts, '*');
++ bool do_merge_add = strchr (flag_bbb_opts, 'm') || strchr (flag_bbb_opts, '*');
++ bool do_elim_dead_assign = strchr (flag_bbb_opts, 'e') || strchr (flag_bbb_opts, '*');
++ bool do_bb_reg_rename = strchr (flag_bbb_opts, 'r') || strchr (flag_bbb_opts, '*');
++ bool do_shrink_stack_frame = strchr (flag_bbb_opts, 'f') || strchr (flag_bbb_opts, '*');
+
+ for (;;)
+ {
+ int done = 1;
+ if (do_opt_strcpy && opt_strcpy ())
+- done = 0, update_meta_data ();
++ done = 0, update_insns ();
+
+ if (do_commute_add_move && commute_add_move ())
+- done = 0, update_meta_data ();
++ done = 0, update_insns ();
+
+ if (do_propagate_moves && propagate_moves ())
+- done = 0, update_meta_data ();
+-
+-// if (offset_2_autoinc ())
+-// done = 0, update_meta_data ();
++ done = 0, update_insns ();
+
++ update_insn_infos ();
+ if (do_const_cmp_to_sub && const_cmp_to_sub ())
+- done = 0, update_meta_data ();
++ done = 0, update_insns (), update_insn_infos ();
+
+ if (do_merge_add && merge_add ())
+- done = 0, update_meta_data ();
++ done = 0, update_insns (), update_insn_infos ();
+
+ if (do_elim_dead_assign && elim_dead_assign ())
+- done = 0, update_meta_data ();
++ done = 0, update_insns ();
+
+-// if (do_bb_reg_rename && bb_reg_rename ())
+-// done = 0, update_meta_data ();
+ if (done)
+ break;
+ }
+
+ if (do_bb_reg_rename && ::global_pass_regrename)
+ {
+- class opt_pass * rr = ::global_pass_regrename->clone();
+- rr->execute(0);
++ class opt_pass * rr = ::global_pass_regrename->clone ();
++ rr->execute (0);
++ update_insns ();
++ }
++
++ if (do_shrink_stack_frame)
++ {
++ shrink_stack_frame ();
++ update_insns ();
+ }
+
+- if (strchr(flag_bbb_opts, 'X')) dump_insns ("bbb 1");
++ if (strchr (flag_bbb_opts, 'X') || strchr (flag_bbb_opts, 'x'))
++ dump_insns ("bbb 1", strchr (flag_bbb_opts, 'X'));
+ clear ();
+
+ return 0;
+diff --git a/gcc/passes.def b/gcc/passes.def
+index ca5b94552d4e..5b78cbd7fb38 100644
+--- gcc/passes.def
++++ gcc/passes.def
+@@ -446,7 +446,6 @@ along with GCC; see the file COPYING3. If not see
+ NEXT_PASS (pass_split_after_reload);
+ NEXT_PASS (pass_ree);
+ NEXT_PASS (pass_compare_elim_after_reload);
+- NEXT_PASS (pass_bbb_optimizations);
+ NEXT_PASS (pass_branch_target_load_optimize1);
+ NEXT_PASS (pass_jump2);
+ NEXT_PASS (pass_duplicate_computed_gotos);
+
+From dcfedefbc4883ebaf068b40920b7830971d02923 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 11 Apr 2017 18:01:13 +0200
+Subject: [PATCH 064/303] @B various bugs, shrink stack frame supports also
+ fp-regs
+
+---
+ gcc/bbb-opts.c | 300 +++++++++++++++++++++++++++++++++++++++++++++------------
+ 1 file changed, 238 insertions(+), 62 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 6114e2fa5ed0..c688ca8ae192 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -43,9 +43,11 @@
+ #include "recog.h"
+ #include "cfgrtl.h"
+ #include "emit-rtl.h"
++#include "tree.h"
+ #include "tree-pass.h"
+ #include "conditions.h"
+ #include "cselib.h"
++#include "langhooks.h"
+ #include <vector>
+ #include <map>
+
+@@ -158,10 +160,16 @@ struct insn_info
+ unsigned
+ get_def_mask () const
+ {
+- if (!_def || _def > 0xffff)
++ if (!_def || _def > 0x7fff)
+ return 0;
+
+ unsigned mask = _def - 1;
++ /* more than one register -> don't touch. */
++ if ((mask & ~_def) != mask)
++ return 0;
++
++ if (_def > 0x1000)
++ return 0;
+ if (_def > 0xff)
+ mask &= 0xff00;
+ return mask;
+@@ -349,6 +357,19 @@ update_insns ()
+ }
+ }
+
++extern struct lang_hooks lang_hooks;
++extern tree current_function_decl;
++static char const *
++getCurrentFunctionName ()
++{
++ static char fxname[512];
++ if (current_function_decl == NULL)
++ strcpy (fxname, "<toplevel>");
++ else
++ strcpy (fxname, lang_hooks.decl_printable_name (current_function_decl, 2));
++ return fxname;
++}
++
+ static void
+ update_insn_infos (void)
+ {
+@@ -401,24 +422,44 @@ update_insn_infos (void)
+
+ if (CALL_P(insn))
+ {
++ insn_info def;
++ insn_info use;
++
+ /* a call sets d0 and maybe also d1,a0,a1. */
+- ii.unset (0);
+- ii.unset (1);
+- ii.unset (8);
+- ii.unset (9);
++ if (ii.is_use(0))
++ def.def (0);
++ if (ii.is_use (1))
++ {
++ fprintf (stderr, ":bbb: use of d1 after call in %s\n", getCurrentFunctionName ());
++ def.def (1);
++ }
++ if (ii.is_use (8))
++ {
++ fprintf (stderr, ":bbb: use of a0 after call in %s\n", getCurrentFunctionName ());
++ def.def (8);
++ }
++ if (ii.is_use (9))
++ {
++ fprintf (stderr, ":bbb: use of a1 after call in %s\n", getCurrentFunctionName ());
++ def.def (9);
++ }
+
+ // FIXME: isuse the DECL and read attributes.
+ // use regs depending on flag mregparm
+ for (int i = 0; i < amigaos_regparm; ++i)
+ {
+- ii.use (i);
+- ii.use (i + 8);
++ use.use (i);
++ use.use (i + 8);
+ }
+
+ // check for reg use
+- ii.scan (pattern);
++ use.scan (pattern);
++
++ infos[pos] = def | use | ii;
++
++ ii &= ~def;
++ ii |= use;
+
+- infos[pos] = ii;
+ continue;
+ }
+
+@@ -720,8 +761,9 @@ propagate_moves ()
+ rtx_insn * after = insns[index + 1];
+ rtx bset = single_set (before);
+
+- fprintf (stderr, ":bbb: propagate_moves condition met, moving regs %d, %d\n",
+- REGNO(srci), REGNO(dsti));
++ fprintf (stderr, ":bbb: propagate_moves condition met, moving regs %s, %s\n",
++ reg_names[REGNO(srci)],
++ reg_names[REGNO(dsti)]);
+
+ /* Move in front of loop and mark as dead. */
+ rtx_insn * newii = make_insn_raw (PATTERN (ii));
+@@ -752,8 +794,6 @@ propagate_moves ()
+ j = reg_reg.end ();
+ inc = false;
+
+-// df_insn_rescan (ii);
+-// df_insn_rescan (jj);
+ df_insn_rescan (newii);
+ df_insn_rescan (newjj);
+
+@@ -813,11 +853,17 @@ opt_strcpy ()
+ rtx_insn * insn = insns[index];
+
+ if (!NONJUMP_INSN_P(insn))
+- continue;
++ {
++ x2reg = 0;
++ continue;
++ }
+
+ rtx set = single_set (insn);
+ if (!set)
+- continue;
++ {
++ x2reg = 0;
++ continue;
++ }
+
+ if (x2reg && reg2x)
+ {
+@@ -845,8 +891,8 @@ opt_strcpy ()
+
+ fprintf (
+ stderr,
+- ":bbb: opt_strcpy condition met, removing compare and joining insns - omit reg %d\n",
+- REGNO(dst));
++ ":bbb: opt_strcpy condition met, removing compare and joining insns - omit reg %s\n",
++ reg_names[REGNO(dst)]);
+
+ SET_SRC(single_set(reg2x)) = SET_SRC(single_set (x2reg));
+
+@@ -1040,15 +1086,12 @@ const_cmp_to_sub (void)
+ // FEATURE: check if the next uses are also a add/sub
+ // then maybe that add/sub can be adjusted too
+
+- // if (!find_reg_note (insn, REG_DEAD, left) || !find_reg_note (insn, REG_DEAD, right))
+- // continue;
+- // use own reg_dead
++// if (!find_reg_note (insn, REG_DEAD, left) || !find_reg_note (insn, REG_DEAD, right))
++// continue;
++ /* use own reg_dead - reg_notes seem to be inaccurate!? */
+ if (!is_reg_dead (REGNO(left), index) || !is_reg_dead (REGNO(right), index))
+ continue;
+
+- fprintf (stderr, ":bbb: found reg-reg compare with both dead: %d %d\n", is_reg_dead (REGNO(left), index),
+- is_reg_dead (REGNO(right), index));
+-
+ // maybe add a search?
+ rtx_insn * prev = insns[index - 1];
+ rtx setp = single_set (prev);
+@@ -1087,12 +1130,6 @@ const_cmp_to_sub (void)
+ SET_INSN_DELETED(prev);
+ prev = emit_insn_before (neuprev, insn);
+
+-// urks - unknown side effects
+-// int omitted_regno = REGNO(dstp);
+-// cselib_invalidate_rtx (dstp);
+-// if (!(df->hard_regs_live_count[omitted_regno] -= 2))
+-// df_set_regs_ever_live (omitted_regno, false);
+-
+ fprintf (stderr, ":bbb: const_cmp_to_sub replaced reg-reg compare with sub\n");
+
+ if (dstp != left)
+@@ -1188,7 +1225,7 @@ elim_dead_assign (void)
+
+ if (is_reg_dead (REGNO(dst), index))
+ {
+- fprintf (stderr, ":bbb: elim_dead_assign to %d\n", REGNO(dst));
++ fprintf (stderr, ":bbb: elim_dead_assign to %s\n", reg_names[REGNO(dst)]);
+ SET_INSN_DELETED(insn);
+ ++change_count;
+ }
+@@ -1311,6 +1348,8 @@ shrink_stack_frame (void)
+
+ bool usea5 = false;
+ unsigned paramstart = 4;
++ int a5offset = 0;
++
+ /*
+ * Move prologue to temp.
+ * Only register push and parallel insn unless its a link a5 are moved.
+@@ -1333,8 +1372,12 @@ shrink_stack_frame (void)
+ rtx set = XVECEXP(pattern, 0, 0);
+ rtx dst = SET_DEST(set);
+ /* ignore link a5 */
+- if (REG_P(dst) && REGNO(dst) == 13)
+- usea5 = true;
++ if (REG_P(dst) && REGNO(dst) == FRAME_POINTER_REGNUM)
++ {
++ usea5 = true;
++ set = XVECEXP(pattern, 0, 2);
++ a5offset = INTVAL(XEXP(SET_SRC(set), 1));
++ }
+ else
+ {
+ /* use movem */
+@@ -1361,7 +1404,7 @@ shrink_stack_frame (void)
+ if (GET_CODE(predec) == PRE_DEC)
+ {
+ rtx reg = XEXP(predec, 0);
+- if (REG_P(reg) && REGNO(reg) == 15)
++ if (REG_P(reg) && REGNO(reg) == STACK_POINTER_REGNUM)
+ {
+ temp[pos] = insn;
+ insns[pos] = 0;
+@@ -1369,12 +1412,12 @@ shrink_stack_frame (void)
+ }
+ }
+ }
+- else if (GET_CODE(src) == PLUS && REG_P(dest) && REGNO(dest) == 15)
++ else if (GET_CODE(src) == PLUS && REG_P(dest) && REGNO(dest) == STACK_POINTER_REGNUM)
+ {
+ /* check for stack variables. */
+ rtx reg = XEXP(src, 0);
+ rtx cx = XEXP(src, 1);
+- if (REG_P(reg) && REGNO(reg) == 15 && CONST_INT_P(cx))
++ if (REG_P(reg) && REGNO(reg) == STACK_POINTER_REGNUM && CONST_INT_P(cx))
+ paramstart -= INTVAL(cx);
+ }
+
+@@ -1390,6 +1433,8 @@ shrink_stack_frame (void)
+
+ unsigned prologueend = pos;
+
++ prev = insn;
++
+ /* search epilogues - there can be multiple epilogues. */
+ while (pos < insns.size ())
+ {
+@@ -1406,6 +1451,7 @@ shrink_stack_frame (void)
+ ++pos;
+ }
+
++
+ /* move epilogues away. */
+ for (; pos < insns.size (); ++pos)
+ {
+@@ -1423,7 +1469,7 @@ shrink_stack_frame (void)
+ rtx set = XVECEXP(pattern, 0, 0);
+ rtx dst = SET_DEST(set);
+ /* unlink is last. */
+- if (REG_P(dst) && REGNO(dst) == 13)
++ if (REG_P(dst) && REGNO(dst) == FRAME_POINTER_REGNUM)
+ break;
+
+ /* movem. */
+@@ -1443,7 +1489,7 @@ shrink_stack_frame (void)
+ if (GET_CODE(postinc) == POST_INC)
+ {
+ rtx reg = XEXP(postinc, 0);
+- if (REG_P(reg) && REGNO(reg) == 15)
++ if (REG_P(reg) && REGNO(reg) == STACK_POINTER_REGNUM)
+ {
+ temp[pos] = insn;
+ insns[pos] = 0;
+@@ -1453,6 +1499,7 @@ shrink_stack_frame (void)
+ }
+ }
+ }
++ prev = insn;
+ ++pos;
+ }
+ /* gather usage stats without prologue/epilogue */
+@@ -1462,7 +1509,8 @@ shrink_stack_frame (void)
+ ii |= infos[i];
+ unsigned freemask = ~ii._use;
+
+- rtx a7 = gen_raw_REG (SImode, 15);
++ rtx a7 = gen_raw_REG (SImode, STACK_POINTER_REGNUM);
++ rtx a5 = gen_raw_REG (SImode, FRAME_POINTER_REGNUM);
+
+ unsigned adjust = 0;
+ /* now all push/pop insns are in temp. */
+@@ -1501,7 +1549,8 @@ shrink_stack_frame (void)
+ unsigned regbit = 1 << REGNO(reg);
+ if (freemask & regbit)
+ {
+- fprintf (stderr, i < prologueend ? "remove push for %d\n" : "remove pop for %d\n", REGNO(reg));
++ fprintf (stderr, i < prologueend ? ":bbb: remove push for %s\n" : ":bbb: remove pop for %s\n",
++ reg_names[REGNO(reg)]);
+ if (i < prologueend)
+ adjust += 4;
+ }
+@@ -1510,11 +1559,12 @@ shrink_stack_frame (void)
+ }
+
+ /* don't touch - clobbers! */
+- if (clobbers.size())
++ if (clobbers.size ())
+ continue;
+
+ if ((int) regs.size () + 1 < XVECLEN(pattern, 0) || regs.size () <= 2)
+ {
++ fprintf (stderr, ":bbb: shrinking stack frame from %d to %d\n", XVECLEN(pattern, 0), regs.size () + 1);
+ if (regs.size () <= 2)
+ {
+ for (unsigned k = 0; k < regs.size (); ++k)
+@@ -1523,16 +1573,16 @@ shrink_stack_frame (void)
+ if (i < prologueend)
+ {
+ /* push */
+- rtx dec = gen_rtx_PRE_DEC(SImode, a7);
+- rtx mem = gen_rtx_MEM (SImode, dec);
++ rtx dec = gen_rtx_PRE_DEC(REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, a7);
++ rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, dec);
+ rtx set = gen_rtx_SET(mem, reg);
+ emit_insn_after (set, insn);
+ }
+ else
+ {
+ /* pop */
+- rtx dec = gen_rtx_POST_INC(SImode, a7);
+- rtx mem = gen_rtx_MEM (SImode, dec);
++ rtx dec = gen_rtx_POST_INC(REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, a7);
++ rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, dec);
+ rtx set = gen_rtx_SET(reg, mem);
+ emit_insn_before (set, insn);
+ }
+@@ -1540,14 +1590,24 @@ shrink_stack_frame (void)
+ }
+ else
+ {
+- rtx parallel = gen_rtx_PARALLEL(VOIDmode, rtvec_alloc (regs.size () + 1));
+- int x = regs.size () * 4 + 4;
++ /* add romm for add. */
++ int add1 = i < prologueend || !usea5 ? 1 : 0;
++ rtx parallel = gen_rtx_PARALLEL(VOIDmode, rtvec_alloc (regs.size () + add1));
++ rtx plus;
++
++ int x = 0;
++ for (unsigned k = 0; k < regs.size (); ++k)
++ x += REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4;
+
+- rtx plus = gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, i < prologueend ? -x : x));
+- XVECEXP(parallel, 0, 0) = gen_rtx_SET(a7, plus);
++ /* no add if a5 is used with pop */
++ if (!usea5 || i < prologueend)
++ {
++ plus = gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, i < prologueend ? -x : x));
++ XVECEXP(parallel, 0, 0) = gen_rtx_SET(a7, plus);
++ }
+
+ if (i >= prologueend)
+- x = 0;
++ x = usea5 ? -x : 0;
+
+ for (unsigned k = 0; k < regs.size (); ++k)
+ {
+@@ -1555,19 +1615,30 @@ shrink_stack_frame (void)
+ {
+ /* push */
+ plus = gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, -x));
+- x -= 4;
+- rtx mem = gen_rtx_MEM (SImode, plus);
++ x -= REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4;
++ rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, plus);
+ rtx set = gen_rtx_SET(mem, regs[k]);
+ XVECEXP(parallel, 0, k + 1) = set;
+ }
+ else
+ {
+ /* pop */
+- plus = x ? gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, x)) : a7;
+- x += 4;
+- rtx mem = gen_rtx_MEM (SImode, plus);
+- rtx set = gen_rtx_SET(regs[k], mem);
+- XVECEXP(parallel, 0, k + 1) = set;
++ if (usea5)
++ {
++ x += REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4;
++ plus = gen_rtx_PLUS(SImode, a5, gen_rtx_CONST_INT (SImode, a5offset + x));
++ rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, plus);
++ rtx set = gen_rtx_SET(regs[k], mem);
++ XVECEXP(parallel, 0, k) = set;
++ }
++ else
++ {
++ plus = x ? gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, x)) : a7;
++ x += REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4;
++ rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, plus);
++ rtx set = gen_rtx_SET(regs[k], mem);
++ XVECEXP(parallel, 0, k + 1) = set;
++ }
+ }
+ }
+ emit_insn_after (parallel, insn);
+@@ -1582,13 +1653,13 @@ shrink_stack_frame (void)
+ if (i < prologueend)
+ {
+ /* move x,-(a7). */
+- paramstart += 4;
+ rtx src = SET_SRC(set);
++ paramstart += REGNO(src) > STACK_POINTER_REGNUM ? 12 : 4;
+ unsigned regbit = 1 << REGNO(src);
+ if (freemask & regbit)
+ {
+- adjust += 4;
+- fprintf (stderr, "remove push for %d\n", REGNO(src));
++ adjust += REGNO(src) > STACK_POINTER_REGNUM ? 12 : 4;
++ fprintf (stderr, ":bbb: remove push for %s\n", reg_names[REGNO(src)]);
+ SET_INSN_DELETED(insn);
+ }
+ }
+@@ -1599,7 +1670,7 @@ shrink_stack_frame (void)
+ unsigned regbit = 1 << REGNO(dst);
+ if (freemask & regbit)
+ {
+- fprintf (stderr, "remove pop for %d\n", REGNO(dst));
++ fprintf (stderr, ":bbb: remove pop for %s\n", reg_names[REGNO(dst)]);
+ SET_INSN_DELETED(insn);
+ }
+ }
+@@ -1626,7 +1697,7 @@ shrink_stack_frame (void)
+ if (GET_CODE(plus) == PLUS)
+ {
+ rtx sp = XEXP(plus, 0);
+- if (REG_P(sp) && REGNO(sp) == 15)
++ if (REG_P(sp) && REGNO(sp) == STACK_POINTER_REGNUM)
+ {
+ rtx c = XEXP(plus, 1);
+ if (CONST_INT_P(c))
+@@ -1647,6 +1718,99 @@ shrink_stack_frame (void)
+ return 0;
+ }
+
++/*
++ * Always prefer lower register numbers within the class.
++ */
++static unsigned
++bb_reg_rename (void)
++{
++ for (unsigned index = 0; index < insns.size (); ++index)
++ {
++ insn_info & ii = infos[index];
++ const unsigned def = ii._def;
++ unsigned mask = ii.get_def_mask ();
++
++ if (!mask)
++ continue;
++
++ std::vector<unsigned> found;
++ std::vector<unsigned> todo;
++ if (index + 1 < insns.size ())
++ todo.push_back (index + 1);
++
++ found.push_back (index);
++ /* a register was defined, follow all branches. */
++ while (todo.size ())
++ {
++ unsigned pos = todo[todo.size () - 1];
++ todo.pop_back ();
++
++ if (LABEL_P(insns[pos]))
++ {
++ if (pos + 1 < insns.size ())
++ todo.push_back (pos + 1);
++ continue;
++ }
++
++ insn_info & jj = infos[pos];
++
++ /* update free regs. */
++ mask &= ~jj._use;
++ mask &= ~jj._def;
++ if (!mask)
++ break;
++
++ /* defined again. */
++ if (jj._def & def)
++ continue;
++
++ /* not referenced. */
++ if (!(jj._use & def))
++ continue;
++
++ found.push_back (pos);
++
++ /* follow jump and/or next insn. */
++ rtx_insn * insn = insns[pos];
++ if (JUMP_P(insn))
++ {
++ std::map<rtx_insn *, unsigned>::iterator j = insn2index.find ((rtx_insn *) JUMP_LABEL(insn));
++ if (j != insn2index.end ())
++ todo.push_back (j->second);
++
++ rtx jmppattern = PATTERN (insn);
++
++ rtx jmpsrc = XEXP(jmppattern, 1);
++ if (GET_CODE(jmpsrc) == IF_THEN_ELSE)
++ if (pos + 1 < insns.size ())
++ todo.push_back (pos + 1);
++ }
++ else if (pos + 1 < insns.size ())
++ todo.push_back (pos + 1);
++ }
++
++ if (mask)
++ {
++ int oldregno = bit2regno (def);
++ int newregno = bit2regno (mask);
++ fprintf (stderr, ":bbb: bb_reg_rename %s -> %s (%d insns)\n", reg_names[oldregno], reg_names[newregno],
++ found.size ());
++
++ for (std::vector<unsigned>::iterator i = found.begin (); i != found.end (); ++i)
++ {
++ debug_rtx (insns[*i]);
++ do_reg_rename (PATTERN (insns[*i]), oldregno, newregno);
++ }
++
++ cselib_invalidate_rtx (gen_raw_REG (SImode, oldregno));
++ cselib_invalidate_rtx (gen_raw_REG (SImode, newregno));
++ return 1;
++ }
++ }
++ return 0;
++}
++
++extern const char * current_function_func_begin_label;
+ extern class opt_pass * global_pass_regrename;
+
+ namespace
+@@ -1676,7 +1840,10 @@ namespace
+ virtual bool
+ gate (function *)
+ {
+- return TARGET_AMIGA && flag_bbb_opts;
++ if (!flag_bbb_opts)
++ flag_bbb_opts = "*";
++
++ return TARGET_AMIGA && optimize > 0 && flag_bbb_opts;
+ }
+
+ virtual unsigned int
+@@ -1704,6 +1871,10 @@ namespace
+ unsigned
+ pass_bbb_optimizations::execute_bbb_optimizations (void)
+ {
++
++ if (strchr (flag_bbb_opts, 'X') || strchr (flag_bbb_opts, 'x'))
++ fprintf (stderr, "%s:\n", current_function_func_begin_label);
++
+ df_set_flags (DF_LR_RUN_DCE + DF_DEFER_INSN_RESCAN);
+ df_note_add_problem ();
+ df_analyze ();
+@@ -1749,6 +1920,11 @@ namespace
+ {
+ class opt_pass * rr = ::global_pass_regrename->clone ();
+ rr->execute (0);
++
++// update_insns ();
++// update_insn_infos ();
++// bb_reg_rename ();
++
+ update_insns ();
+ }
+
+
+From 56aa60f1154c2988edf35ba30ec259a798ba61f2 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 13 Apr 2017 23:49:13 +0200
+Subject: [PATCH 065/303] @B fix stack frame handling and suspicious other
+ stuff
+
+---
+ gcc/bbb-opts.c | 80 ++++++++++++++++++++++++++++++----------------------------
+ gcc/final.c | 7 ++++-
+ 2 files changed, 48 insertions(+), 39 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index c688ca8ae192..56251b906184 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -182,7 +182,8 @@ insn_info::scan (rtx x)
+ {
+ if (REG_P(x))
+ {
+- use (REGNO(x));
++ for (int n = REG_NREGS(x), r = REGNO(x); n > 0; --n, ++r)
++ use (r);
+ return;
+ }
+
+@@ -425,35 +426,34 @@ update_insn_infos (void)
+ insn_info def;
+ insn_info use;
+
+- /* a call sets d0 and maybe also d1,a0,a1. */
+- if (ii.is_use(0))
+- def.def (0);
+- if (ii.is_use (1))
+- {
+- fprintf (stderr, ":bbb: use of d1 after call in %s\n", getCurrentFunctionName ());
+- def.def (1);
+- }
+- if (ii.is_use (8))
++ /* add mregparm registers. */
++ for (rtx link = CALL_INSN_FUNCTION_USAGE(insn); link; link = XEXP(link, 1))
+ {
+- fprintf (stderr, ":bbb: use of a0 after call in %s\n", getCurrentFunctionName ());
+- def.def (8);
+- }
+- if (ii.is_use (9))
+- {
+- fprintf (stderr, ":bbb: use of a1 after call in %s\n", getCurrentFunctionName ());
+- def.def (9);
++ rtx op, reg;
++
++ if (GET_CODE (op = XEXP (link, 0)) == USE && REG_P(reg = XEXP (op, 0)))
++ for (int r = REGNO(reg); r <= END_REGNO (reg); ++r)
++ use.use (r);
+ }
+
+- // FIXME: isuse the DECL and read attributes.
+- // use regs depending on flag mregparm
+- for (int i = 0; i < amigaos_regparm; ++i)
++ rtx set = single_set (insn);
++ if (set)
+ {
+- use.use (i);
+- use.use (i + 8);
++ use.scan (SET_SRC(set));
++ def.scan (SET_DEST(set));
+ }
++ else
++ use.scan (pattern);
+
+- // check for reg use
+- use.scan (pattern);
++ /* fix missing defs - a call sets d0 and maybe also d1,a0,a1. */
++ if (ii.is_use (0))
++ def.def (0);
++ if (ii.is_use (1))
++ def.def (1);
++ if (ii.is_use (8))
++ def.def (8);
++ if (ii.is_use (9))
++ def.def (9);
+
+ infos[pos] = def | use | ii;
+
+@@ -494,7 +494,7 @@ update_insn_infos (void)
+ continue;
+ }
+
+- if (GET_CODE (pattern) != PARALLEL)
++ if (GET_CODE (pattern) != PARALLEL && GET_CODE (pattern) != CLOBBER)
+ {
+ fprintf (stderr, "##### ");
+ debug_rtx (insn);
+@@ -1062,7 +1062,7 @@ const_cmp_to_sub (void)
+ {
+ unsigned change_count = 0;
+ #if HAVE_cc0
+- for (unsigned index = insns.size () - 2; index > 0; --index)
++ for (int index = insns.size () - 2; index > 0; --index)
+ {
+ rtx_insn * insn = insns[index];
+ rtx seti = single_set (insn);
+@@ -1079,7 +1079,7 @@ const_cmp_to_sub (void)
+
+ rtx left = XEXP(srci, 0);
+ rtx right = XEXP(srci, 1);
+- if (!REG_P(left) || !REG_P(right))
++ if (!REG_P(left) || !REG_P(right) || REG_NREGS(left) > 1 || REG_NREGS(right) > 1)
+ continue;
+
+ // TODO
+@@ -1451,7 +1451,6 @@ shrink_stack_frame (void)
+ ++pos;
+ }
+
+-
+ /* move epilogues away. */
+ for (; pos < insns.size (); ++pos)
+ {
+@@ -1506,7 +1505,12 @@ shrink_stack_frame (void)
+ update_insn_infos ();
+ insn_info ii;
+ for (unsigned i = 0; i < infos.size (); ++i)
+- ii |= infos[i];
++ {
++ insn_info & jj = infos[i];
++ ii |= jj;
++// fprintf (stderr, "%08lx %08lx\n", jj._use, jj._def);
++ }
++// fprintf (stderr, "%08lx %08lx\n", ii._use, ii._def);
+ unsigned freemask = ~ii._use;
+
+ rtx a7 = gen_raw_REG (SImode, STACK_POINTER_REGNUM);
+@@ -1562,9 +1566,15 @@ shrink_stack_frame (void)
+ if (clobbers.size ())
+ continue;
+
+- if ((int) regs.size () + 1 < XVECLEN(pattern, 0) || regs.size () <= 2)
++ /* add romm for add.
++ * push is always using -(a7) addressing.
++ * If a5 is used a movem offset(a5) is generated to pop saved registers..
++ * Otherwise a7 is used and with (a7)+ addressing.
++ */
++ int add1 = i < prologueend || !usea5 ? 1 : 0;
++ if ((int) regs.size () + add1 < XVECLEN(pattern, 0) || regs.size () <= 2)
+ {
+- fprintf (stderr, ":bbb: shrinking stack frame from %d to %d\n", XVECLEN(pattern, 0), regs.size () + 1);
++ fprintf (stderr, ":bbb: shrinking stack frame from %d to %d\n", XVECLEN(pattern, 0) - add1, regs.size ());
+ if (regs.size () <= 2)
+ {
+ for (unsigned k = 0; k < regs.size (); ++k)
+@@ -1590,8 +1600,6 @@ shrink_stack_frame (void)
+ }
+ else
+ {
+- /* add romm for add. */
+- int add1 = i < prologueend || !usea5 ? 1 : 0;
+ rtx parallel = gen_rtx_PARALLEL(VOIDmode, rtvec_alloc (regs.size () + add1));
+ rtx plus;
+
+@@ -1856,7 +1864,7 @@ namespace
+ clone ()
+ {
+ pass_bbb_optimizations * bbb = new pass_bbb_optimizations (m_ctxt);
+- // bbb->pp = pp + 1;
++ bbb->pp = pp + 1;
+ return bbb;
+ }
+
+@@ -1871,10 +1879,6 @@ namespace
+ unsigned
+ pass_bbb_optimizations::execute_bbb_optimizations (void)
+ {
+-
+- if (strchr (flag_bbb_opts, 'X') || strchr (flag_bbb_opts, 'x'))
+- fprintf (stderr, "%s:\n", current_function_func_begin_label);
+-
+ df_set_flags (DF_LR_RUN_DCE + DF_DEFER_INSN_RESCAN);
+ df_note_add_problem ();
+ df_analyze ();
+diff --git a/gcc/final.c b/gcc/final.c
+index 55cf509611f7..9d21ffc1baff 100644
+--- gcc/final.c
++++ gcc/final.c
+@@ -2165,7 +2165,7 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
+
+ /* Ignore deleted insns. These can occur when we split insns (due to a
+ template of "#") while not optimizing. */
+- if (insn->deleted ())
++ if (insn->deleted () || GET_CODE(insn) == VALUE || GET_CODE(insn) == CONST_FIXED)
+ return NEXT_INSN (insn);
+
+ switch (GET_CODE (insn))
+@@ -4430,12 +4430,17 @@ leaf_renumber_regs_insn (rtx in_rtx)
+ }
+ #endif
+
++
++extern void dump_insns(char const *);
++
+ /* Turn the RTL into assembly. */
+ static unsigned int
+ rest_of_handle_final (void)
+ {
+ const char *fnname = get_fnname_from_decl (current_function_decl);
+
++// dump_insns("final");
++
+ assemble_start_function (current_function_decl, fnname);
+ final_start_function (get_insns (), asm_out_file, optimize);
+ final (get_insns (), asm_out_file, optimize);
+
+From 51c5b7b668483ac0cdc30a3fee718754a03bcca9 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 14 Apr 2017 18:33:26 +0200
+Subject: [PATCH 066/303] @R add option description for command line help
+
+---
+ gcc/config/m68k/amigaos.opt | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt
+index a5a14449dea9..9c08ba43196e 100644
+--- gcc/config/m68k/amigaos.opt
++++ gcc/config/m68k/amigaos.opt
+@@ -25,24 +25,24 @@ small code model
+
+ fbaserel
+ Target Report Var(flag_pic,3)
+-data is adressed relativ to a4
++data is addressed relative to a4
+
+ fbaserel32
+ Target Report Var(flag_pic,4)
+-data is adressed relativ to a4 with 32 bit offsets
++data is addressed relative to a4 with 32 bit offsets
+
+ resident
+ Target Common Report Var(flag_pic,3)
+-data is adressed relativ to a4, linked as resident
++data is addressed relative to a4, linked as resident
+
+ resident32
+ Target Common Report Var(flag_pic,4)
+-data is adressed relativ to a4 with 32 bit offsets, linked as resident
++data is addressed relative to a4 with 32 bit offsets, linked as resident
+
+ mcrt=
+ Target RejectNegative Var(amigaos_crt) Joined
+ Specify startup binary
+
+ fbbb=
+-Target Var(flag_bbb_opts) Joined
+-Enable Bebbo's optimizations
++Target RejectNegative Report Var(string_bbb_opts) Joined
++-fbbb=\t\tEnable Bebbo's optimizations. Default: -fbbb=+\n valid letters:\n\t\t+\t\tenable all\n\t\t-\t\tdisable all\n\t\ta\t\tadd move optimization\n\t\tc\t\tcompare to sub\n\t\te\t\teliminate dead assignments\n\t\tf\t\tshrink stack frame\n\t\tm\t\tmerge add statements\n\t\tp\t\tpropagate move pairs from loops\n\t\tr\t\tadditional reg rename pass\n\t\tv\t\tbe verbose\n\t\tx or X\t\tdump insns
+
+From 5abbd0e25e9cc50d4449884567079df90141511b Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 14 Apr 2017 18:34:31 +0200
+Subject: [PATCH 067/303] @B resolv issues to get everything built
+
+---
+ gcc/bbb-opts.c | 255 +++++++++++++++++++--------------------------------------
+ gcc/final.c | 2 +-
+ gcc/passes.def | 6 +-
+ 3 files changed, 89 insertions(+), 174 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 56251b906184..1b1863e9ae8f 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -51,6 +51,42 @@
+ #include <vector>
+ #include <map>
+
++static bool be_verbose;
++
++extern struct lang_hooks lang_hooks;
++extern tree current_function_decl;
++static tree last_function_decl;
++static char const *
++getCurrentFunctionName ()
++{
++ static char fxname[512];
++ if (current_function_decl == NULL)
++ strcpy (fxname, "<toplevel>");
++ else
++ strcpy (fxname, lang_hooks.decl_printable_name (current_function_decl, 2));
++ return fxname;
++}
++
++static int
++log (char const * fmt, ...)
++{
++ if (!be_verbose)
++ return 0;
++
++ va_list args;
++ va_start(args, fmt);
++ if (last_function_decl != current_function_decl)
++ {
++ last_function_decl = current_function_decl;
++ printf (":bbb: in '%s'\n", getCurrentFunctionName ());
++ }
++ printf (":bbb: ");
++ int retval = vprintf (fmt, args);
++ va_end(args);
++ fflush (stdout);
++ return retval;
++}
++
+ /* Enough for m68k.
+ * Why a class? Maybe extend it for general usage.
+ *
+@@ -231,21 +267,6 @@ do_reg_rename (rtx x, unsigned oldregno, unsigned newregno)
+ }
+ }
+
+-static int
+-bit2regno (unsigned bit)
+-{
+- if (!bit)
+- return -1;
+-
+- unsigned regno = 0;
+- while (!(bit & 1))
+- {
+- ++regno;
+- bit >>= 1;
+- }
+- return regno;
+-}
+-
+ /*
+ * Collect some data.
+ */
+@@ -358,19 +379,6 @@ update_insns ()
+ }
+ }
+
+-extern struct lang_hooks lang_hooks;
+-extern tree current_function_decl;
+-static char const *
+-getCurrentFunctionName ()
+-{
+- static char fxname[512];
+- if (current_function_decl == NULL)
+- strcpy (fxname, "<toplevel>");
+- else
+- strcpy (fxname, lang_hooks.decl_printable_name (current_function_decl, 2));
+- return fxname;
+-}
+-
+ static void
+ update_insn_infos (void)
+ {
+@@ -432,7 +440,7 @@ update_insn_infos (void)
+ rtx op, reg;
+
+ if (GET_CODE (op = XEXP (link, 0)) == USE && REG_P(reg = XEXP (op, 0)))
+- for (int r = REGNO(reg); r <= END_REGNO (reg); ++r)
++ for (unsigned r = REGNO(reg); r <= END_REGNO (reg); ++r)
+ use.use (r);
+ }
+
+@@ -468,7 +476,7 @@ update_insn_infos (void)
+ if (ANY_RETURN_P(pattern))
+ {
+ ii.reset ();
+- ii.use (0);
++// ii.use (0);
+ }
+ else
+ {
+@@ -494,7 +502,7 @@ update_insn_infos (void)
+ continue;
+ }
+
+- if (GET_CODE (pattern) != PARALLEL && GET_CODE (pattern) != CLOBBER)
++ if (GET_CODE (pattern) != PARALLEL && GET_CODE (pattern) != CLOBBER && be_verbose)
+ {
+ fprintf (stderr, "##### ");
+ debug_rtx (insn);
+@@ -761,9 +769,9 @@ propagate_moves ()
+ rtx_insn * after = insns[index + 1];
+ rtx bset = single_set (before);
+
+- fprintf (stderr, ":bbb: propagate_moves condition met, moving regs %s, %s\n",
++ log ("propagate_moves condition met, moving regs %s, %s\n",
+ reg_names[REGNO(srci)],
+- reg_names[REGNO(dsti)]);
++ reg_names[REGNO(dsti)]);
+
+ /* Move in front of loop and mark as dead. */
+ rtx_insn * newii = make_insn_raw (PATTERN (ii));
+@@ -800,7 +808,7 @@ propagate_moves ()
+ /* add fixes if there were jumps out of the loop. */
+ if (jump_out.size ())
+ {
+- fprintf (stderr, ":bbb: propagate_moves fixing %d jump outs\n", jump_out.size ());
++ log ("propagate_moves fixing %d jump outs\n", jump_out.size ());
+
+ for (unsigned k = 0; k < jump_out.size (); ++k)
+ {
+@@ -873,7 +881,8 @@ opt_strcpy ()
+ rtx dst = XEXP(src, 0);
+ src = XEXP(src, 1);
+
+- if (CONST_INT_P(src) && INTVAL(src) == 0 && find_reg_note (insn, REG_DEAD, dst))
++// if (CONST_INT_P(src) && INTVAL(src) == 0 && find_reg_note (insn, REG_DEAD, dst))
++ if (REG_P(dst) && CONST_INT_P(src) && INTVAL(src) == 0 && is_reg_dead(REGNO(dst), index))
+ {
+ /* now check via NOTICE_UPDATE_CC*/
+ NOTICE_UPDATE_CC(PATTERN (reg2x), reg2x);
+@@ -889,10 +898,8 @@ opt_strcpy ()
+ {
+ rtx link;
+
+- fprintf (
+- stderr,
+- ":bbb: opt_strcpy condition met, removing compare and joining insns - omit reg %s\n",
+- reg_names[REGNO(dst)]);
++ log ("opt_strcpy condition met, removing compare and joining insns - omit reg %s\n",
++ reg_names[REGNO(dst)]);
+
+ SET_SRC(single_set(reg2x)) = SET_SRC(single_set (x2reg));
+
+@@ -1017,7 +1024,7 @@ commute_add_move (void)
+
+ if (validate_change (next, &SET_DEST(set2), newmem, 0))
+ {
+- fprintf (stderr, ":bbb: commute_add_move found\n");
++ log ("commute_add_move found\n");
+
+ SET_INSN_DELETED(insn);
+
+@@ -1130,7 +1137,7 @@ const_cmp_to_sub (void)
+ SET_INSN_DELETED(prev);
+ prev = emit_insn_before (neuprev, insn);
+
+- fprintf (stderr, ":bbb: const_cmp_to_sub replaced reg-reg compare with sub\n");
++ log ("const_cmp_to_sub replaced reg-reg compare with sub\n");
+
+ if (dstp != left)
+ {
+@@ -1191,7 +1198,7 @@ const_cmp_to_sub (void)
+
+ if (code != newcode)
+ {
+- fprintf (stderr, ":bbb: patch jcc %d -> %d\n", code, newcode);
++ log ("patch jcc %d -> %d\n", code, newcode);
+ XEXP(jmpsrc, 0) = gen_rtx_fmt_ee(newcode, VOIDmode, XEXP(condition, 0), XEXP(condition, 1));
+ }
+ }
+@@ -1225,7 +1232,7 @@ elim_dead_assign (void)
+
+ if (is_reg_dead (REGNO(dst), index))
+ {
+- fprintf (stderr, ":bbb: elim_dead_assign to %s\n", reg_names[REGNO(dst)]);
++ log ("elim_dead_assign to %s\n", reg_names[REGNO(dst)]);
+ SET_INSN_DELETED(insn);
+ ++change_count;
+ }
+@@ -1291,13 +1298,15 @@ merge_add (void)
+ if (REGNO(dst1) != REGNO(dst2) || REGNO(r2) != REGNO(dst3))
+ continue;
+
+- fprintf (stderr, ":bbb: merge_add applied\n");
++ log ("merge_add applied\n");
++
++ rtx_insn * newins1 = make_insn_raw(gen_rtx_SET(dst1, l1));
++ add_insn_after (newins1, ins1, 0);
++ SET_INSN_DELETED(ins1);
+
+- SET_SRC(set1) = l1;
+ rtx_insn * newins2 = make_insn_raw (PATTERN (ins2));
+ add_insn_after (newins2, ins3, 0);
+ SET_INSN_DELETED(ins2);
+- df_insn_rescan (ins1);
+ }
+ return change_count;
+ }
+@@ -1508,9 +1517,7 @@ shrink_stack_frame (void)
+ {
+ insn_info & jj = infos[i];
+ ii |= jj;
+-// fprintf (stderr, "%08lx %08lx\n", jj._use, jj._def);
+ }
+-// fprintf (stderr, "%08lx %08lx\n", ii._use, ii._def);
+ unsigned freemask = ~ii._use;
+
+ rtx a7 = gen_raw_REG (SImode, STACK_POINTER_REGNUM);
+@@ -1553,7 +1560,7 @@ shrink_stack_frame (void)
+ unsigned regbit = 1 << REGNO(reg);
+ if (freemask & regbit)
+ {
+- fprintf (stderr, i < prologueend ? ":bbb: remove push for %s\n" : ":bbb: remove pop for %s\n",
++ log (i < prologueend ? "remove push for %s\n" : "remove pop for %s\n",
+ reg_names[REGNO(reg)]);
+ if (i < prologueend)
+ adjust += 4;
+@@ -1574,7 +1581,7 @@ shrink_stack_frame (void)
+ int add1 = i < prologueend || !usea5 ? 1 : 0;
+ if ((int) regs.size () + add1 < XVECLEN(pattern, 0) || regs.size () <= 2)
+ {
+- fprintf (stderr, ":bbb: shrinking stack frame from %d to %d\n", XVECLEN(pattern, 0) - add1, regs.size ());
++ log ("shrinking stack frame from %d to %d\n", XVECLEN(pattern, 0) - add1, regs.size ());
+ if (regs.size () <= 2)
+ {
+ for (unsigned k = 0; k < regs.size (); ++k)
+@@ -1667,7 +1674,7 @@ shrink_stack_frame (void)
+ if (freemask & regbit)
+ {
+ adjust += REGNO(src) > STACK_POINTER_REGNUM ? 12 : 4;
+- fprintf (stderr, ":bbb: remove push for %s\n", reg_names[REGNO(src)]);
++ log ("remove push for %s\n", reg_names[REGNO(src)]);
+ SET_INSN_DELETED(insn);
+ }
+ }
+@@ -1678,7 +1685,7 @@ shrink_stack_frame (void)
+ unsigned regbit = 1 << REGNO(dst);
+ if (freemask & regbit)
+ {
+- fprintf (stderr, ":bbb: remove pop for %s\n", reg_names[REGNO(dst)]);
++ log ("remove pop for %s\n", reg_names[REGNO(dst)]);
+ SET_INSN_DELETED(insn);
+ }
+ }
+@@ -1726,99 +1733,6 @@ shrink_stack_frame (void)
+ return 0;
+ }
+
+-/*
+- * Always prefer lower register numbers within the class.
+- */
+-static unsigned
+-bb_reg_rename (void)
+-{
+- for (unsigned index = 0; index < insns.size (); ++index)
+- {
+- insn_info & ii = infos[index];
+- const unsigned def = ii._def;
+- unsigned mask = ii.get_def_mask ();
+-
+- if (!mask)
+- continue;
+-
+- std::vector<unsigned> found;
+- std::vector<unsigned> todo;
+- if (index + 1 < insns.size ())
+- todo.push_back (index + 1);
+-
+- found.push_back (index);
+- /* a register was defined, follow all branches. */
+- while (todo.size ())
+- {
+- unsigned pos = todo[todo.size () - 1];
+- todo.pop_back ();
+-
+- if (LABEL_P(insns[pos]))
+- {
+- if (pos + 1 < insns.size ())
+- todo.push_back (pos + 1);
+- continue;
+- }
+-
+- insn_info & jj = infos[pos];
+-
+- /* update free regs. */
+- mask &= ~jj._use;
+- mask &= ~jj._def;
+- if (!mask)
+- break;
+-
+- /* defined again. */
+- if (jj._def & def)
+- continue;
+-
+- /* not referenced. */
+- if (!(jj._use & def))
+- continue;
+-
+- found.push_back (pos);
+-
+- /* follow jump and/or next insn. */
+- rtx_insn * insn = insns[pos];
+- if (JUMP_P(insn))
+- {
+- std::map<rtx_insn *, unsigned>::iterator j = insn2index.find ((rtx_insn *) JUMP_LABEL(insn));
+- if (j != insn2index.end ())
+- todo.push_back (j->second);
+-
+- rtx jmppattern = PATTERN (insn);
+-
+- rtx jmpsrc = XEXP(jmppattern, 1);
+- if (GET_CODE(jmpsrc) == IF_THEN_ELSE)
+- if (pos + 1 < insns.size ())
+- todo.push_back (pos + 1);
+- }
+- else if (pos + 1 < insns.size ())
+- todo.push_back (pos + 1);
+- }
+-
+- if (mask)
+- {
+- int oldregno = bit2regno (def);
+- int newregno = bit2regno (mask);
+- fprintf (stderr, ":bbb: bb_reg_rename %s -> %s (%d insns)\n", reg_names[oldregno], reg_names[newregno],
+- found.size ());
+-
+- for (std::vector<unsigned>::iterator i = found.begin (); i != found.end (); ++i)
+- {
+- debug_rtx (insns[*i]);
+- do_reg_rename (PATTERN (insns[*i]), oldregno, newregno);
+- }
+-
+- cselib_invalidate_rtx (gen_raw_REG (SImode, oldregno));
+- cselib_invalidate_rtx (gen_raw_REG (SImode, newregno));
+- return 1;
+- }
+- }
+- return 0;
+-}
+-
+-extern const char * current_function_func_begin_label;
+ extern class opt_pass * global_pass_regrename;
+
+ namespace
+@@ -1848,10 +1762,10 @@ namespace
+ virtual bool
+ gate (function *)
+ {
+- if (!flag_bbb_opts)
+- flag_bbb_opts = "*";
++ if (!string_bbb_opts)
++ string_bbb_opts = "+";
+
+- return TARGET_AMIGA && optimize > 0 && flag_bbb_opts;
++ return TARGET_AMIGA && optimize > 0 && string_bbb_opts && !strchr (string_bbb_opts, '-');
+ }
+
+ virtual unsigned int
+@@ -1883,20 +1797,21 @@ namespace
+ df_note_add_problem ();
+ df_analyze ();
+
+- update_insns ();
++ be_verbose = strchr (string_bbb_opts, 'v');
+
+- bool do_opt_strcpy = strchr (flag_bbb_opts, 's') || strchr (flag_bbb_opts, '*');
+- bool do_commute_add_move = strchr (flag_bbb_opts, 'a') || strchr (flag_bbb_opts, '*');
+- bool do_propagate_moves = strchr (flag_bbb_opts, 'p') || strchr (flag_bbb_opts, '*');
+- bool do_const_cmp_to_sub = strchr (flag_bbb_opts, 'c') || strchr (flag_bbb_opts, '*');
+- bool do_merge_add = strchr (flag_bbb_opts, 'm') || strchr (flag_bbb_opts, '*');
+- bool do_elim_dead_assign = strchr (flag_bbb_opts, 'e') || strchr (flag_bbb_opts, '*');
+- bool do_bb_reg_rename = strchr (flag_bbb_opts, 'r') || strchr (flag_bbb_opts, '*');
+- bool do_shrink_stack_frame = strchr (flag_bbb_opts, 'f') || strchr (flag_bbb_opts, '*');
++ bool do_opt_strcpy = strchr (string_bbb_opts, 's') || strchr (string_bbb_opts, '+');
++ bool do_commute_add_move = strchr (string_bbb_opts, 'a') || strchr (string_bbb_opts, '+');
++ bool do_propagate_moves = strchr (string_bbb_opts, 'p') || strchr (string_bbb_opts, '+');
++ bool do_const_cmp_to_sub = strchr (string_bbb_opts, 'c') || strchr (string_bbb_opts, '+');
++ bool do_merge_add = strchr (string_bbb_opts, 'm') || strchr (string_bbb_opts, '+');
++ bool do_elim_dead_assign = strchr (string_bbb_opts, 'e') || strchr (string_bbb_opts, '+');
++ bool do_bb_reg_rename = strchr (string_bbb_opts, 'r') || strchr (string_bbb_opts, '+');
++ bool do_shrink_stack_frame = strchr (string_bbb_opts, 'f') || strchr (string_bbb_opts, '+');
+
+ for (;;)
+ {
+ int done = 1;
++ update_insns ();
+ if (do_opt_strcpy && opt_strcpy ())
+ done = 0, update_insns ();
+
+@@ -1916,20 +1831,20 @@ namespace
+ if (do_elim_dead_assign && elim_dead_assign ())
+ done = 0, update_insns ();
+
+- if (done)
+- break;
+- }
++ if (do_bb_reg_rename && ::global_pass_regrename)
++ {
++ class opt_pass * rr = ::global_pass_regrename->clone ();
++ rr->execute (0);
+
+- if (do_bb_reg_rename && ::global_pass_regrename)
+- {
+- class opt_pass * rr = ::global_pass_regrename->clone ();
+- rr->execute (0);
++ // update_insns ();
++ // update_insn_infos ();
++ // bb_reg_rename ();
+
+-// update_insns ();
+-// update_insn_infos ();
+-// bb_reg_rename ();
++ update_insns ();
++ }
+
+- update_insns ();
++ if (done)
++ break;
+ }
+
+ if (do_shrink_stack_frame)
+@@ -1938,8 +1853,8 @@ namespace
+ update_insns ();
+ }
+
+- if (strchr (flag_bbb_opts, 'X') || strchr (flag_bbb_opts, 'x'))
+- dump_insns ("bbb 1", strchr (flag_bbb_opts, 'X'));
++ if (strchr (string_bbb_opts, 'X') || strchr (string_bbb_opts, 'x'))
++ dump_insns ("bbb", strchr (string_bbb_opts, 'X'));
+ clear ();
+
+ return 0;
+diff --git a/gcc/final.c b/gcc/final.c
+index 9d21ffc1baff..31f9b4815d75 100644
+--- gcc/final.c
++++ gcc/final.c
+@@ -2165,7 +2165,7 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
+
+ /* Ignore deleted insns. These can occur when we split insns (due to a
+ template of "#") while not optimizing. */
+- if (insn->deleted () || GET_CODE(insn) == VALUE || GET_CODE(insn) == CONST_FIXED)
++ if (insn->deleted () || GET_CODE(insn) == VALUE || GET_CODE(insn) == CONST_FIXED || GET_CODE(insn) == DEBUG_IMPLICIT_PTR)
+ return NEXT_INSN (insn);
+
+ switch (GET_CODE (insn))
+diff --git a/gcc/passes.def b/gcc/passes.def
+index 5b78cbd7fb38..f48fd2581cba 100644
+--- gcc/passes.def
++++ gcc/passes.def
+@@ -447,6 +447,9 @@ along with GCC; see the file COPYING3. If not see
+ NEXT_PASS (pass_ree);
+ NEXT_PASS (pass_compare_elim_after_reload);
+ NEXT_PASS (pass_branch_target_load_optimize1);
++ NEXT_PASS (pass_thread_prologue_and_epilogue);
++ NEXT_PASS (pass_rtl_dse2);
++ NEXT_PASS (pass_stack_adjustments);
+ NEXT_PASS (pass_jump2);
+ NEXT_PASS (pass_duplicate_computed_gotos);
+ NEXT_PASS (pass_sched_fusion);
+@@ -454,9 +457,6 @@ along with GCC; see the file COPYING3. If not see
+ NEXT_PASS (pass_if_after_reload);
+ NEXT_PASS (pass_regrename);
+ NEXT_PASS (pass_cprop_hardreg);
+- NEXT_PASS (pass_thread_prologue_and_epilogue);
+- NEXT_PASS (pass_rtl_dse2);
+- NEXT_PASS (pass_stack_adjustments);
+ NEXT_PASS (pass_fast_rtl_dce);
+ NEXT_PASS (pass_reorder_blocks);
+ NEXT_PASS (pass_bbb_optimizations);
+
+From 7c3f103835a555944b28e4e2a0726f33830abc6a Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 14 Apr 2017 18:35:14 +0200
+Subject: [PATCH 068/303] @N add eclipse project files
+
+---
+ .cproject | 180 +++++++++++++++++++++++++++++
+ .project | 16 +++
+ .settings/language.settings.xml | 25 ++++
+ .settings/org.eclipse.cdt.codan.core.prefs | 71 ++++++++++++
+ .settings/org.eclipse.cdt.core.prefs | 6 +
+ .settings/org.eclipse.core.runtime.prefs | 5 +
+ 6 files changed, 303 insertions(+)
+ create mode 100755 .cproject
+ create mode 100755 .settings/language.settings.xml
+ create mode 100755 .settings/org.eclipse.cdt.codan.core.prefs
+ create mode 100755 .settings/org.eclipse.cdt.core.prefs
+ create mode 100755 .settings/org.eclipse.core.runtime.prefs
+
+diff --git a/.cproject b/.cproject
+new file mode 100755
+index 000000000000..62b1c0f38dcb
+--- /dev/null
++++ .cproject
+@@ -0,0 +1,180 @@
++<?xml version="1.0" encoding="UTF-8" standalone="no"?>
++<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
++ <storageModule moduleId="org.eclipse.cdt.core.settings">
++ <cconfiguration id="cdt.managedbuild.config.gnu.cross.exe.debug.452878522">
++ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.cross.exe.debug.452878522" moduleId="org.eclipse.cdt.core.settings" name="Debug">
++ <externalSettings/>
++ <extensions>
++ <extension id="org.eclipse.cdt.core.Cygwin_PE" point="org.eclipse.cdt.core.BinaryParser"/>
++ <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
++ <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
++ <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
++ <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
++ <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
++ </extensions>
++ </storageModule>
++ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
++ <configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.debug.452878522" name="Debug" parent="cdt.managedbuild.config.gnu.cross.exe.debug">
++ <folderInfo id="cdt.managedbuild.config.gnu.cross.exe.debug.452878522." name="/" resourcePath="">
++ <toolChain id="cdt.managedbuild.toolchain.gnu.cygwin.base.2053847551" name="Cygwin GCC" superClass="cdt.managedbuild.toolchain.gnu.cygwin.base">
++ <targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.Cygwin_PE" id="cdt.managedbuild.target.gnu.platform.cygwin.base.2091243283" name="Debug Platform" osList="win32" superClass="cdt.managedbuild.target.gnu.platform.cygwin.base"/>
++ <builder buildPath="${workspace_loc:/debugwin}/Debug" id="cdt.managedbuild.target.gnu.builder.cygwin.base.1660320342" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.cygwin.base">
++ <outputEntries>
++ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name=""/>
++ </outputEntries>
++ </builder>
++ <tool id="cdt.managedbuild.tool.gnu.assembler.cygwin.base.607722454" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.cygwin.base">
++ <option id="gnu.both.asm.option.include.paths.2094451885" name="Include paths (-I)" superClass="gnu.both.asm.option.include.paths" valueType="includePath">
++ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/amigaos-cross-toolchain/.build-m68k/build/gcc-6/gcc}&quot;"/>
++ <listOptionValue builtIn="false" value="&quot;C:\cygwin\usr\include&quot;"/>
++ </option>
++ <inputType id="cdt.managedbuild.tool.gnu.assembler.input.1425989952" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
++ </tool>
++ <tool id="cdt.managedbuild.tool.gnu.archiver.cygwin.base.2119049474" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.cygwin.base"/>
++ <tool id="cdt.managedbuild.tool.gnu.cpp.compiler.cygwin.base.1103847968" name="Cygwin C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.cygwin.base">
++ <option id="gnu.cpp.compiler.option.include.paths.466783605" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
++ <listOptionValue builtIn="false" value="&quot;C:\cygwin\usr\include&quot;"/>
++ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/gcc-6/libcpp/include}&quot;"/>
++ <listOptionValue builtIn="false" value="&quot;D:\develop\workspaces\c1\amigaos-cross-toolchain\.build-m68k\build\gcc-6\gcc&quot;"/>
++ </option>
++ <option id="gnu.cpp.compiler.option.optimization.level.193715843" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/>
++ <option id="gnu.cpp.compiler.option.debugging.level.2136883244" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.max" valueType="enumerated"/>
++ <option id="gnu.cpp.compiler.option.preprocessor.def.807277038" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols">
++ <listOptionValue builtIn="false" value="IN_GCC=1"/>
++ <listOptionValue builtIn="false" value="HAVE_cc0=1"/>
++ </option>
++ <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.cygwin.780175803" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input.cygwin"/>
++ </tool>
++ <tool id="cdt.managedbuild.tool.gnu.c.compiler.cygwin.base.1920331604" name="Cygwin C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.cygwin.base">
++ <option id="gnu.c.compiler.option.include.paths.692774379" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
++ <listOptionValue builtIn="false" value="&quot;C:\cygwin\usr\include&quot;"/>
++ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/gcc-6/libcpp/include}&quot;"/>
++ <listOptionValue builtIn="false" value="&quot;D:\develop\workspaces\c1\amigaos-cross-toolchain\.build-m68k\build\gcc-6\gcc&quot;"/>
++ </option>
++ <option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.option.optimization.level.227992926" name="Optimization Level" superClass="gnu.c.compiler.option.optimization.level" useByScannerDiscovery="false" valueType="enumerated"/>
++ <option id="gnu.c.compiler.option.debugging.level.748883400" name="Debug Level" superClass="gnu.c.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.max" valueType="enumerated"/>
++ <option id="gnu.c.compiler.option.preprocessor.def.symbols.1982594045" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols">
++ <listOptionValue builtIn="false" value="IN_GCC=1"/>
++ <listOptionValue builtIn="false" value="HAVE_cc0=1"/>
++ </option>
++ <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.cygwin.2078467313" superClass="cdt.managedbuild.tool.gnu.c.compiler.input.cygwin"/>
++ </tool>
++ <tool id="cdt.managedbuild.tool.gnu.c.linker.cygwin.base.344641511" name="Cygwin C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.cygwin.base"/>
++ <tool id="cdt.managedbuild.tool.gnu.cpp.linker.cygwin.base.968200320" name="Cygwin C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.cygwin.base">
++ <option id="gnu.cpp.link.option.libs.260033787" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" valueType="libs"/>
++ <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1537937183" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
++ <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
++ <additionalInput kind="additionalinput" paths="$(LIBS)"/>
++ </inputType>
++ </tool>
++ </toolChain>
++ </folderInfo>
++ <sourceEntries>
++ <entry excluding="ada/|doc/|fortran/|ginclude/|go/|java/|jit/|lto/|objc/|objcp/|po/|testsuite/|config/aarch64/|config/alpha/|config/arc/|config/arm/|config/avr/|config/bfin/|config/c6x/|config/cr16/|config/cris/|config/epiphany/|config/fr30/|config/frv/|config/ft32/|config/h8300/|config/i386/|config/ia64/|config/iq2000/|config/lm32/|config/m32c/|config/m32r/|config/mcore/|config/mep/|config/microblaze/|config/mips/|config/mmix/|config/mn10300/|config/moxie/|config/msp430/|config/nds32/|config/nios2/|config/nvptx/|config/pa/|config/pdp11/|config/rl78/|config/rs6000/|config/rx/|config/s390/|config/sh/|config/sparc/|config/spu/|config/stormy16/|config/tilegx/|config/tilepro/|config/v850/|config/vax/|config/visium/|config/vms/|config/xtensa/" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="gcc"/>
++ </sourceEntries>
++ </configuration>
++ </storageModule>
++ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
++ </cconfiguration>
++ <cconfiguration id="cdt.managedbuild.config.gnu.cross.exe.release.811454954">
++ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.cross.exe.release.811454954" moduleId="org.eclipse.cdt.core.settings" name="Release">
++ <externalSettings/>
++ <extensions>
++ <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
++ <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
++ <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
++ <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
++ <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
++ <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
++ </extensions>
++ </storageModule>
++ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
++ <configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.release.811454954" name="Release" parent="cdt.managedbuild.config.gnu.cross.exe.release">
++ <folderInfo id="cdt.managedbuild.config.gnu.cross.exe.release.811454954." name="/" resourcePath="">
++ <toolChain id="cdt.managedbuild.toolchain.gnu.cross.exe.release.101222491" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.exe.release">
++ <targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.1798723854" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/>
++ <builder buildPath="${workspace_loc:/debugwin}/Release" id="cdt.managedbuild.builder.gnu.cross.507087034" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="cdt.managedbuild.builder.gnu.cross"/>
++ <tool id="cdt.managedbuild.tool.gnu.cross.c.compiler.1834281466" name="Cross GCC Compiler" superClass="cdt.managedbuild.tool.gnu.cross.c.compiler">
++ <option defaultValue="gnu.c.optimization.level.most" id="gnu.c.compiler.option.optimization.level.1686563067" name="Optimization Level" superClass="gnu.c.compiler.option.optimization.level" useByScannerDiscovery="false" valueType="enumerated"/>
++ <option id="gnu.c.compiler.option.debugging.level.60172226" name="Debug Level" superClass="gnu.c.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.none" valueType="enumerated"/>
++ <option id="gnu.c.compiler.option.include.paths.696908692" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
++ <listOptionValue builtIn="false" value="&quot;C:\cygwin\usr\include&quot;"/>
++ </option>
++ <option id="gnu.c.compiler.option.preprocessor.def.symbols.652362073" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols">
++ <listOptionValue builtIn="false" value="IN_GCC=1"/>
++ <listOptionValue builtIn="false" value="HAVE_cc0=1"/>
++ </option>
++ <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1150724656" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
++ </tool>
++ <tool id="cdt.managedbuild.tool.gnu.cross.cpp.compiler.1042604749" name="Cross G++ Compiler" superClass="cdt.managedbuild.tool.gnu.cross.cpp.compiler">
++ <option id="gnu.cpp.compiler.option.optimization.level.2088586809" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.most" valueType="enumerated"/>
++ <option id="gnu.cpp.compiler.option.debugging.level.1993778911" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/>
++ <option id="gnu.cpp.compiler.option.include.paths.1936413739" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
++ <listOptionValue builtIn="false" value="&quot;C:\cygwin\usr\include&quot;"/>
++ </option>
++ <option id="gnu.cpp.compiler.option.preprocessor.def.625117841" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols">
++ <listOptionValue builtIn="false" value="IN_GCC=1"/>
++ <listOptionValue builtIn="false" value="HAVE_cc0=1"/>
++ </option>
++ <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1133865092" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
++ </tool>
++ <tool id="cdt.managedbuild.tool.gnu.cross.c.linker.946489608" name="Cross GCC Linker" superClass="cdt.managedbuild.tool.gnu.cross.c.linker"/>
++ <tool id="cdt.managedbuild.tool.gnu.cross.cpp.linker.738916918" name="Cross G++ Linker" superClass="cdt.managedbuild.tool.gnu.cross.cpp.linker">
++ <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1880308865" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
++ <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
++ <additionalInput kind="additionalinput" paths="$(LIBS)"/>
++ </inputType>
++ </tool>
++ <tool id="cdt.managedbuild.tool.gnu.cross.archiver.1813524686" name="Cross GCC Archiver" superClass="cdt.managedbuild.tool.gnu.cross.archiver"/>
++ <tool id="cdt.managedbuild.tool.gnu.cross.assembler.1395544547" name="Cross GCC Assembler" superClass="cdt.managedbuild.tool.gnu.cross.assembler">
++ <option id="gnu.both.asm.option.include.paths.1443815690" name="Include paths (-I)" superClass="gnu.both.asm.option.include.paths" valueType="includePath">
++ <listOptionValue builtIn="false" value="&quot;C:\cygwin\usr\include&quot;"/>
++ </option>
++ <inputType id="cdt.managedbuild.tool.gnu.assembler.input.1421786104" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
++ </tool>
++ </toolChain>
++ </folderInfo>
++ <sourceEntries>
++ <entry excluding="src" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
++ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
++ </sourceEntries>
++ </configuration>
++ </storageModule>
++ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
++ </cconfiguration>
++ </storageModule>
++ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
++ <project id="debugwin.cdt.managedbuild.target.gnu.cross.exe.1884740625" name="Executable" projectType="cdt.managedbuild.target.gnu.cross.exe"/>
++ </storageModule>
++ <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
++ <storageModule moduleId="refreshScope" versionNumber="2">
++ <configuration configurationName="Debug">
++ <resource resourceType="PROJECT" workspacePath="/gcc-6"/>
++ </configuration>
++ <configuration configurationName="Release">
++ <resource resourceType="PROJECT" workspacePath="/gcc-6"/>
++ </configuration>
++ </storageModule>
++ <storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
++ <storageModule moduleId="scannerConfiguration">
++ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
++ <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.cross.exe.release.811454954;cdt.managedbuild.config.gnu.cross.exe.release.811454954.;cdt.managedbuild.tool.gnu.cross.c.compiler.1834281466;cdt.managedbuild.tool.gnu.c.compiler.input.1150724656">
++ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
++ </scannerConfigBuildInfo>
++ <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.cross.exe.debug.452878522;cdt.managedbuild.config.gnu.cross.exe.debug.452878522.;cdt.managedbuild.tool.gnu.cross.c.compiler.502147450;cdt.managedbuild.tool.gnu.c.compiler.input.1173428818">
++ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
++ </scannerConfigBuildInfo>
++ <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.cross.exe.debug.452878522;cdt.managedbuild.config.gnu.cross.exe.debug.452878522.;cdt.managedbuild.tool.gnu.cpp.compiler.cygwin.base.1103847968;cdt.managedbuild.tool.gnu.cpp.compiler.input.cygwin.780175803">
++ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
++ </scannerConfigBuildInfo>
++ <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.cross.exe.debug.452878522;cdt.managedbuild.config.gnu.cross.exe.debug.452878522.;cdt.managedbuild.tool.gnu.c.compiler.cygwin.base.1920331604;cdt.managedbuild.tool.gnu.c.compiler.input.cygwin.2078467313">
++ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
++ </scannerConfigBuildInfo>
++ <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.cross.exe.debug.452878522;cdt.managedbuild.config.gnu.cross.exe.debug.452878522.;cdt.managedbuild.tool.gnu.cross.cpp.compiler.216739552;cdt.managedbuild.tool.gnu.cpp.compiler.input.1269341019">
++ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
++ </scannerConfigBuildInfo>
++ <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.cross.exe.release.811454954;cdt.managedbuild.config.gnu.cross.exe.release.811454954.;cdt.managedbuild.tool.gnu.cross.cpp.compiler.1042604749;cdt.managedbuild.tool.gnu.cpp.compiler.input.1133865092">
++ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
++ </scannerConfigBuildInfo>
++ </storageModule>
++</cproject>
+diff --git a/.project b/.project
+index ab5c4b198d08..22b8c5a11f48 100644
+--- .project
++++ .project
+@@ -5,7 +5,23 @@
+ <projects>
+ </projects>
+ <buildSpec>
++ <buildCommand>
++ <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
++ <triggers>clean,full,incremental,</triggers>
++ <arguments>
++ </arguments>
++ </buildCommand>
++ <buildCommand>
++ <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
++ <triggers>full,incremental,</triggers>
++ <arguments>
++ </arguments>
++ </buildCommand>
+ </buildSpec>
+ <natures>
++ <nature>org.eclipse.cdt.core.cnature</nature>
++ <nature>org.eclipse.cdt.core.ccnature</nature>
++ <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
++ <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+ </natures>
+ </projectDescription>
+diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml
+new file mode 100755
+index 000000000000..c6ac9211311a
+--- /dev/null
++++ .settings/language.settings.xml
+@@ -0,0 +1,25 @@
++<?xml version="1.0" encoding="UTF-8" standalone="no"?>
++<project>
++ <configuration id="cdt.managedbuild.config.gnu.cross.exe.debug.452878522" name="Debug">
++ <extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
++ <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
++ <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
++ <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
++ <provider class="org.eclipse.cdt.managedbuilder.internal.language.settings.providers.GCCBuiltinSpecsDetectorCygwin" console="false" env-hash="1253352314297216180" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetectorCygwin" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings Cygwin" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
++ <language-scope id="org.eclipse.cdt.core.gcc"/>
++ <language-scope id="org.eclipse.cdt.core.g++"/>
++ </provider>
++ </extension>
++ </configuration>
++ <configuration id="cdt.managedbuild.config.gnu.cross.exe.release.811454954" name="Release">
++ <extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
++ <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
++ <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
++ <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
++ <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="860895942062206931" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
++ <language-scope id="org.eclipse.cdt.core.gcc"/>
++ <language-scope id="org.eclipse.cdt.core.g++"/>
++ </provider>
++ </extension>
++ </configuration>
++</project>
+diff --git a/.settings/org.eclipse.cdt.codan.core.prefs b/.settings/org.eclipse.cdt.codan.core.prefs
+new file mode 100755
+index 000000000000..b5248c620107
+--- /dev/null
++++ .settings/org.eclipse.cdt.codan.core.prefs
+@@ -0,0 +1,71 @@
++eclipse.preferences.version=1
++org.eclipse.cdt.codan.checkers.errnoreturn=Warning
++org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return\\")",implicit\=>false}
++org.eclipse.cdt.codan.checkers.errreturnvalue=Error
++org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused return value\\")"}
++org.eclipse.cdt.codan.checkers.nocommentinside=-Error
++org.eclipse.cdt.codan.checkers.nocommentinside.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Nesting comments\\")"}
++org.eclipse.cdt.codan.checkers.nolinecomment=-Error
++org.eclipse.cdt.codan.checkers.nolinecomment.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Line comments\\")"}
++org.eclipse.cdt.codan.checkers.noreturn=Error
++org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return value\\")",implicit\=>false}
++org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error
++org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Abstract class cannot be instantiated\\")"}
++org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error
++org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Ambiguous problem\\")"}
++org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning
++org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment in condition\\")"}
++org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error
++org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment to itself\\")"}
++org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning
++org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No break at end of case\\")",no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false}
++org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning
++org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Catching by reference is recommended\\")",unknown\=>false,exceptions\=>()}
++org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error
++org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Circular inheritance\\")"}
++org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning
++org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class members should be properly initialized\\")",skip\=>true}
++org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error
++org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Field cannot be resolved\\")"}
++org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error
++org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Function cannot be resolved\\")"}
++org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error
++org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid arguments\\")"}
++org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error
++org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid template argument\\")"}
++org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error
++org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Label statement not found\\")"}
++org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error
++org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Member declaration not found\\")"}
++org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error
++org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Method cannot be resolved\\")"}
++org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info
++org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Name convention for function\\")",pattern\=>"^[a-z]",macro\=>true,exceptions\=>()}
++org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning
++org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class has a virtual method and non-virtual destructor\\")"}
++org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error
++org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid overload\\")"}
++org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error
++org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redeclaration\\")"}
++org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error
++org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redefinition\\")"}
++org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning
++org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Return with parenthesis\\")"}
++org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning
++org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Format String Vulnerability\\")"}
++org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning
++org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Statement has no effect\\")",macro\=>true,exceptions\=>()}
++org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning
++org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suggested parenthesis around expression\\")",paramNot\=>false}
++org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning
++org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suspicious semicolon\\")",else\=>false,afterelse\=>false}
++org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error
++org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Type cannot be resolved\\")"}
++org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning
++org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused function declaration\\")",macro\=>true}
++org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning
++org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused static function\\")",macro\=>true}
++org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning
++org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused variable declaration in file scope\\")",macro\=>true,exceptions\=>("@(\#)","$Id")}
++org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error
++org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Symbol is not resolved\\")"}
+diff --git a/.settings/org.eclipse.cdt.core.prefs b/.settings/org.eclipse.cdt.core.prefs
+new file mode 100755
+index 000000000000..8ec9fe72ca59
+--- /dev/null
++++ .settings/org.eclipse.cdt.core.prefs
+@@ -0,0 +1,6 @@
++eclipse.preferences.version=1
++environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.452878522/PATH/delimiter=;
++environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.452878522/PATH/operation=replace
++environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.452878522/PATH/value=C\:\\WINDOWS\\system32;C\:\\WINDOWS;C\:\\Program Files\\SlikSvn\\bin;C\:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0;c\:\\cygwin\\bin;D\:\\develop\\workspaces\\c1\\amigaos-cross-toolchain\\m68k-amigaos\\bin
++environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.452878522/append=true
++environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.452878522/appendContributed=true
+diff --git a/.settings/org.eclipse.core.runtime.prefs b/.settings/org.eclipse.core.runtime.prefs
+new file mode 100755
+index 000000000000..12511e62a174
+--- /dev/null
++++ .settings/org.eclipse.core.runtime.prefs
+@@ -0,0 +1,5 @@
++content-types/enabled=true
++content-types/org.eclipse.cdt.core.cHeader/file-extensions=def
++content-types/org.eclipse.cdt.core.cxxHeader/file-extensions=h
++content-types/org.eclipse.cdt.core.cxxSource/file-extensions=c
++eclipse.preferences.version=1
+
+From 4920a3ed01948bcc777d84e3c42f4e92310ee499 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 19 Apr 2017 13:38:11 +0200
+Subject: [PATCH 069/303] @R be nice to other windows programs and replace
+ /cygdrive/x/ with x:/ -> include/lib path discovery is now working in Eclipse
+ running on Windows
+
+---
+ gcc/gcc.c | 8 ++++----
+ libiberty/lrealpath.c | 18 +++++++++++++++++-
+ 2 files changed, 21 insertions(+), 5 deletions(-)
+
+diff --git a/gcc/gcc.c b/gcc/gcc.c
+index 33ca41545736..2974b91300ca 100644
+--- gcc/gcc.c
++++ gcc/gcc.c
+@@ -10109,7 +10109,7 @@ const char * amiga_m68k_prefix_func(int argc, const char ** argv) {
+ char * p = 0;
+ if (standard_libexec_prefix)
+ {
+- char * glp = concat(standard_libexec_prefix, "",0);
++ char * glp = concat(standard_libexec_prefix, "", NULL);
+ p = strrchr(glp, '/');
+ if (p)
+ {
+@@ -10122,17 +10122,17 @@ const char * amiga_m68k_prefix_func(int argc, const char ** argv) {
+ if (p)
+ {
+ p[1] = 0;
+- p = concat(glp, "m68k-amigaos/", 0);
++ p = concat(glp, "m68k-amigaos/", NULL);
+ }
+ }
+ }
+ free(glp);
+ }
+ if (!p)
+- p = concat("../../../../", "", 0);
++ p = concat("../../../../", "", NULL);
+
+ for (int i = 0; i < argc; ++i) {
+- char * q = concat(p, argv[i], 0);
++ char * q = concat(p, argv[i], NULL);
+ free(p);
+ p = q;
+ }
+diff --git a/libiberty/lrealpath.c b/libiberty/lrealpath.c
+index b27c8de990e9..78c06e46da58 100644
+--- libiberty/lrealpath.c
++++ libiberty/lrealpath.c
+@@ -73,7 +73,7 @@ extern char *canonicalize_file_name (const char *);
+ #endif
+
+ char *
+-lrealpath (const char *filename)
++__xlrealpath (const char *filename)
+ {
+ /* Method 1: The system has a compile time upper bound on a filename
+ path. Use that and realpath() to canonicalize the name. This is
+@@ -155,3 +155,19 @@ lrealpath (const char *filename)
+ /* This system is a lost cause, just duplicate the filename. */
+ return strdup (filename);
+ }
++
++
++char *
++lrealpath (const char *filename)
++{
++ char * r = __xlrealpath(filename);
++#if defined (_WIN32)
++ if (strncmp(r, "/cygdrive/", 10) == 0)
++ {
++ r[9] = r[10];
++ r[10] = ':';
++ r = strdup(&r[9]);
++ }
++#endif
++ return r;
++}
+
+From f6379a10611d6376109a63b65768387905a30490 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 19 Apr 2017 13:41:44 +0200
+Subject: [PATCH 070/303] @B fix rename-registers if using register parameters:
+ add clobbers for the regs
+
+---
+ gcc/config/m68k/amigaos.c | 1671 +++++++++++++++++++++++----------------------
+ gcc/config/m68k/m68k.c | 6 +
+ 2 files changed, 842 insertions(+), 835 deletions(-)
+
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index 88205e25476e..ca8eea305345 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -1,835 +1,836 @@
+-/* Configuration for GNU C-compiler for m68k Amiga, running AmigaOS.
+- Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2003
+- Free Software Foundation, Inc.
+- Contributed by Markus M. Wild (wild@amiga.physik.unizh.ch).
+- Heavily modified by Kamil Iskra (iskra@student.uci.agh.edu.pl).
+-
+-This file is part of GCC.
+-
+-GCC 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.
+-
+-GCC 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 GCC; see the file COPYING. If not, write to
+-the Free Software Foundation, 59 Temple Place - Suite 330,
+-Boston, MA 02111-1307, USA. */
+-
+-//work without flag_writable_strings which is not in GCC4
+-#define REGPARMS_68K 1
+-
+-#include "config.h"
+-#include "system.h"
+-#include "coretypes.h"
+-#include "tm.h"
+-#include "rtl.h"
+-#include "output.h"
+-#include "tree.h"
+-#include "attribs.h"
+-#include "flags.h"
+-#include "expr.h"
+-#include "toplev.h"
+-#include "tm_p.h"
+-#include "target.h"
+-#include "diagnostic-core.h"
+-#include "config/m68k/amigaos.h"
+-
+-//#define MYDEBUG 1
+-#ifdef MYDEBUG
+-#define DPRINTF(x) printf x; fflush(stdout);
+-#else
+-#define DPRINTF(x)
+-#endif
+-
+-//int amiga_declare_object;
+-
+-#if 0
+-static int amigaos_put_in_text (tree);
+-static rtx gen_stack_management_call (rtx, rtx, const char *);
+-
+-/* Baserel support. */
+-
+-/* Does operand (which is a symbolic_operand) live in text space? If
+- so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true.
+-
+- This function is used in base relative code generation. */
+-
+-int
+-read_only_operand (rtx operand)
+-{
+- if (GET_CODE (operand) == CONST)
+- operand = XEXP (XEXP (operand, 0), 0);
+- if (GET_CODE (operand) == SYMBOL_REF)
+- return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand);
+- return 1;
+-}
+-
+-/* Choose the section to use for DECL. RELOC is true if its value contains
+- any relocatable expression. */
+-
+-void
+-amigaos_select_section (tree decl ATTRIBUTE_UNUSED, int reloc ATTRIBUTE_UNUSED,
+- unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
+-{
+- // if (TREE_CODE (decl) == STRING_CST)
+-// {
+-//// flag_writable_strings /data_section not in gcc4,
+-////make life easy and put to same section
+-//// if (! flag_writable_strings)
+-//// readonly_data_section ();
+-//// else
+-// //data_section ();
+-// }
+-// else if (TREE_CODE (decl) == VAR_DECL)
+-// {
+-// if (TREE_READONLY (decl)
+-// && ! TREE_THIS_VOLATILE (decl)
+-// && DECL_INITIAL (decl)
+-// && (DECL_INITIAL (decl) == error_mark_node
+-// || TREE_CONSTANT (DECL_INITIAL (decl)))
+-// && (!flag_pic || (flag_pic<3 && !reloc)
+-// || SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0))))
+-// readonly_data_section ();
+-// else
+-// data_section ();
+-// }
+-// else if ((!flag_pic || (flag_pic<3 && !reloc)) && DECL_P(decl)
+-// && SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)))
+-// readonly_data_section ();
+-// else
+- //data_section ();
+-}
+-
+-/* This function is used while generating a base relative code.
+- It returns 1 if a decl is not relocatable, i. e., if it can be put
+- in the text section.
+- Currently, it's very primitive: it just checks if the object size
+- is less than 4 bytes (i. e., if it can hold a pointer). It also
+- supports arrays and floating point types. */
+-
+-static int
+-amigaos_put_in_text (tree decl)
+-{
+- tree type = TREE_TYPE (decl);
+- if (TREE_CODE (type) == ARRAY_TYPE)
+- type = TREE_TYPE (type);
+- return (TREE_INT_CST_ELT(TYPE_SIZE (type), 1) == 0
+- && TREE_INT_CST_LOW (TYPE_SIZE (type)) < 32)
+- || FLOAT_TYPE_P (type);
+-}
+-
+-/* Record properties of a DECL into the associated SYMBOL_REF. */
+-
+-void
+-amigaos_encode_section_info (tree decl, rtx rtl, int first)
+-{
+- default_encode_section_info (decl, rtl, first);
+-
+-
+- SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
+- if (TREE_CODE (decl) == FUNCTION_DECL) // huh seem do same. not in gcc4 flag_writable_strings
+- SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
+- else
+- {
+- if ((MEM_READONLY_P (rtl) && !MEM_VOLATILE_P (rtl)
+- && (flag_pic<3 || (TREE_CODE (decl) == STRING_CST
+- )
+- || amigaos_put_in_text (decl)))
+- || (TREE_CODE (decl) == VAR_DECL
+- && DECL_SECTION_NAME (decl) != NULL))
+- SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
+- }
+-}
+-
+-/* Common routine used to check if a4 should be preserved/restored. */
+-
+-int
+-amigaos_restore_a4 (void)
+-{
+- return (flag_pic >= 3 &&
+- (TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4
+- || lookup_attribute ("saveds",
+- TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))));
+-}
+-
+-void
+-amigaos_alternate_pic_setup (FILE *stream)
+-{
+- if (TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4)
+- asm_fprintf (stream, "\tjbsr %U__restore_a4\n");
+- else if (lookup_attribute ("saveds",
+- TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
+- asm_fprintf (stream, "\tlea %U__a4_init,%Ra4\n");
+-}
+-
+-/* Attributes support. */
+-
+-#define AMIGA_CHIP_SECTION_NAME ".datachip"
+-
+-/* Handle a "chip" attribute;
+- arguments as in struct attribute_spec.handler. */
+-
+-tree
+-amigaos_handle_decl_attribute (tree *node, tree name,
+- tree args ATTRIBUTE_UNUSED,
+- int flags ATTRIBUTE_UNUSED,
+- bool *no_add_attrs)
+-{
+- if (TREE_CODE (*node) == VAR_DECL)
+- {
+- if (is_attribute_p ("chip", name))
+-#ifdef TARGET_ASM_NAMED_SECTION
+- {
+- if (! TREE_STATIC (*node) && ! DECL_EXTERNAL (*node))
+- error ("`chip' attribute cannot be specified for local variables");
+- else
+- {
+- /* The decl may have already been given a section attribute from
+- a previous declaration. Ensure they match. */
+- if (DECL_SECTION_NAME (*node) == NULL_TREE)
+- DECL_SECTION_NAME (*node) =
+- build_string (strlen (AMIGA_CHIP_SECTION_NAME) + 1,
+- AMIGA_CHIP_SECTION_NAME);
+- else if (strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (*node)),
+- AMIGA_CHIP_SECTION_NAME) != 0)
+- {
+- error_with_decl (*node,
+- "`chip' for `%s' conflicts with previous declaration");
+- }
+- }
+- }
+-#else
+- error ("`chip' attribute is not supported for this target");
+-#endif
+- }
+- else
+- {
+- warning (OPT_Wattributes, "`%s' attribute only applies to variables",
+- IDENTIFIER_POINTER (name));
+- *no_add_attrs = true;
+- }
+-
+- return NULL_TREE;
+-}
+-
+-//----- from 68k.c start
+-
+-
+-
+-
+-
+-
+-/* Stack checking and automatic extension support. */
+-
+-void
+-amigaos_prologue_begin_hook (FILE *stream, int fsize)
+-{
+- if (TARGET_STACKCHECK)
+- {
+- if (fsize < 256)
+- asm_fprintf (stream, "\tcmpl %s,%Rsp\n"
+- "\tjcc 0f\n"
+- "\tjra %U__stkovf\n"
+- "\t0:\n",
+- (flag_pic == 3 ? "a4@(___stk_limit:W)" :
+- (flag_pic == 4 ? "a4@(___stk_limit:L)" :
+- "___stk_limit")));
+- else
+- asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__stkchk_d0\n",
+- fsize);
+- }
+-}
+-
+-void
+-amigaos_alternate_frame_setup_f (FILE *stream, int fsize)
+-{
+- if (fsize < 128)
+- asm_fprintf (stream, "\tcmpl %s,%Rsp\n"
+- "\tjcc 0f\n"
+- "\tmoveq %I%d,%Rd0\n"
+- "\tmoveq %I0,%Rd1\n"
+- "\tjbsr %U__stkext_f\n"
+- "0:\tlink %Ra5,%I%d:W\n",
+- (flag_pic == 3 ? "a4@(___stk_limit:W)" :
+- (flag_pic == 4 ? "a4@(___stk_limit:L)" :
+- "___stk_limit")),
+- fsize, -fsize);
+- else
+- asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__link_a5_d0_f\n",
+- fsize);
+-}
+-
+-void
+-amigaos_alternate_frame_setup (FILE *stream, int fsize)
+-{
+- if (!fsize)
+- asm_fprintf (stream, "\tcmpl %s,%Rsp\n"
+- "\tjcc 0f\n"
+- "\tmoveq %I0,%Rd0\n"
+- "\tmoveq %I0,%Rd1\n"
+- "\tjbsr %U__stkext_f\n"
+- "0:\n",
+- (flag_pic == 3 ? "a4@(___stk_limit:W)" :
+- (flag_pic == 4 ? "a4@(___stk_limit:L)" :
+- "___stk_limit")));
+- else if (fsize < 128)
+- asm_fprintf (stream, "\tcmpl %s,%Rsp\n"
+- "\tjcc 0f\n"
+- "\tmoveq %I%d,%Rd0\n"
+- "\tmoveq %I0,%Rd1\n"
+- "\tjbsr %U__stkext_f\n"
+- "0:\taddw %I%d,%Rsp\n",
+- (flag_pic == 3 ? "a4@(___stk_limit:W)" :
+- (flag_pic == 4 ? "a4@(___stk_limit:L)" :
+- "___stk_limit")),
+- fsize, -fsize);
+- else
+- asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__sub_d0_sp_f\n",
+- fsize);
+-}
+-
+-//static rtx
+-//gen_stack_management_call (rtx stack_pointer, rtx arg, const char *func)
+-//{
+-// rtx call_insn, call, seq, name;
+-// start_sequence ();
+-//
+-// /* Move arg to d0. */
+-// emit_move_insn (gen_rtx_REG (SImode, 0), arg);
+-//
+-// /* Generate the function reference. */
+-// name = gen_rtx_SYMBOL_REF (Pmode, func);
+-// SYMBOL_REF_FLAG (name) = 1;
+-// /* If optimizing, put it in a psedo so that several loads can be merged
+-// into one. */
+-// if (optimize && ! flag_no_function_cse)
+-// name = copy_to_reg (name);
+-//
+-// /* Generate the function call. */
+-// call = gen_rtx_CALL (VOIDmode, gen_rtx_MEM (FUNCTION_MODE, name),
+-// const0_rtx);
+-// /* If we are doing stack extension, notify about the sp change. */
+-// if (stack_pointer)
+-// call = gen_rtx_SET (VOIDmode, stack_pointer, call);
+-//
+-// /* Generate the call instruction. */
+-// call_insn = emit_call_insn (call);
+-// /* Stack extension does not change memory in an unpredictable way. */
+-// RTL_CONST_OR_PURE_CALL_P (call_insn) = 1;
+-// /* We pass an argument in d0. */
+-// CALL_INSN_FUNCTION_USAGE (call_insn) = gen_rtx_EXPR_LIST (VOIDmode,
+-// gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, 0)), 0);
+-//
+-// seq = get_insns ();
+-// end_sequence ();
+-// return seq;
+-//}
+-//
+-//rtx
+-//gen_stack_cleanup_call (rtx stack_pointer, rtx sa)
+-//{
+-// return gen_stack_management_call (stack_pointer, sa, "__move_d0_sp");
+-//}
+-//
+-//void
+-//amigaos_alternate_allocate_stack (rtx *operands)
+-//{
+-// if (TARGET_STACKEXTEND)
+-// emit_insn (gen_stack_management_call (stack_pointer_rtx, operands[1],
+-// "__sub_d0_sp"));
+-// else
+-// {
+-// if (TARGET_STACKCHECK)
+-// emit_insn (gen_stack_management_call (0, operands[1], "__stkchk_d0"));
+-// anti_adjust_stack (operands[1]);
+-// }
+-// emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
+-//}
+-#endif
+-
+-/*
+- * begin-GG-local: explicit register specification for parameters.
+- *
+- * Reworked and ported to gcc-6.2.0 by Stefan "Bebbo" Franke.
+- */
+-
+-/**
+- * Define this here and add it to tm_p -> all know the custom type and allocate/use the correct size.
+- */
+-struct amigaos_args
+-{
+- int num_of_regs;
+- long regs_already_used;
+- int last_arg_reg;
+- int last_arg_len;
+- tree formal_type; /* New field: formal type of the current argument. */
+-};
+-
+-static struct amigaos_args mycum;
+-static CUMULATIVE_ARGS * lastcum;
+-
+-/* Argument-passing support functions. */
+-
+-/* Initialize a variable CUM of type CUMULATIVE_ARGS
+- for a call to a function whose data type is FNTYPE.
+- For a library call, FNTYPE is 0. */
+-
+-void
+-amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl)
+-{
+- struct amigaos_args * cum = &mycum;
+- lastcum = cump;
+- cum->num_of_regs = amigaos_regparm > 0 ? amigaos_regparm : 0;
+- DPRINTF(("0amigaos_init_cumulative_args %p -> %d\r\n", cum, cum->num_of_regs));
+-
+- /* Initialize a variable CUM of type CUMULATIVE_ARGS
+- for a call to a function whose data type is FNTYPE.
+- For a library call, FNTYPE is 0. */
+-
+- cum->last_arg_reg = -1;
+- cum->regs_already_used = 0;
+-
+- if (decl)
+- {
+- tree attrs = DECL_ATTRIBUTES(decl);
+- if (lookup_attribute ("stkparm", attrs))
+- cum->num_of_regs = 0;
+- else
+- {
+- tree ratree = lookup_attribute ("regparm", attrs);
+- cum->num_of_regs = amigaos_regparm != 0 ?
+- amigaos_regparm : AMIGAOS_DEFAULT_REGPARM;
+- if (ratree)
+- {
+- tree args = TREE_VALUE(ratree);
+-
+- if (args && TREE_CODE (args) == TREE_LIST)
+- {
+- tree val = TREE_VALUE(args);
+- if (TREE_CODE (val) == INTEGER_CST)
+- {
+- int no = TREE_INT_CST_LOW(val);
+- if (no > 0 && no < AMIGAOS_MAX_REGPARM)
+- cum->num_of_regs = no;
+- }
+- }
+- }
+- }
+- }
+- else
+- /* Libcall. */
+- cum->num_of_regs = 0;
+-
+- if (cum->num_of_regs)
+- {
+- /* If this is a vararg call, put all arguments on stack. */
+- tree param, next_param;
+- for (param = TYPE_ARG_TYPES(fntype); param; param = next_param)
+- {
+- next_param = TREE_CHAIN(param);
+- if (!next_param && TREE_VALUE (param) != void_type_node)
+- cum->num_of_regs = 0;
+- }
+- }
+-
+- //#if ! defined (PCC_STATIC_STRUCT_RETURN) && defined (M68K_STRUCT_VALUE_REGNUM)
+- // /* If return value is a structure, and we pass the buffer address in a
+- // register, we can't use this register for our own purposes.
+- // FIXME: Something similar would be useful for static chain. */
+- // if (fntype && aggregate_value_p (TREE_TYPE (fntype), fntype))
+- // cum->regs_already_used |= (1 << M68K_STRUCT_VALUE_REGNUM);
+- //#endif
+-
+- if (fntype)
+- cum->formal_type = TYPE_ARG_TYPES(fntype);
+- else
+- /* Call to compiler-support function. */
+- cum->formal_type = 0;
+- DPRINTF(("1amigaos_init_cumulative_args %p -> %d\r\n", cum, cum->num_of_regs));
+-}
+-
+-/* Update the data in CUM to advance over an argument. */
+-
+-void
+-amigaos_function_arg_advance (cumulative_args_t cum_v, machine_mode, const_tree,
+- bool)
+-{
+- struct amigaos_args * cum = &mycum;
+- CUMULATIVE_ARGS *cump = (CUMULATIVE_ARGS *) get_cumulative_args (cum_v);
+- /* Update the data in CUM to advance over an argument. */
+-
+- DPRINTF(("amigaos_function_arg_advance1 %p\r\n", cump));
+- if (cump != lastcum)
+- return;
+-
+- if (cum->last_arg_reg != -1)
+- {
+- int count;
+- for (count = 0; count < cum->last_arg_len; count++)
+- cum->regs_already_used |= (1 << (cum->last_arg_reg + count));
+- cum->last_arg_reg = -1;
+- }
+-
+- if (cum->formal_type)
+- cum->formal_type = TREE_CHAIN(cum->formal_type);
+-}
+-
+-/* Define where to put the arguments to a function.
+- Value is zero to push the argument on the stack,
+- or a hard register in which to store the argument.
+-
+- MODE is the argument's machine mode.
+- TYPE is the data type of the argument (as a tree).
+- This is null for libcalls where that information may
+- not be available.
+- CUM is a variable of type CUMULATIVE_ARGS which gives info about
+- the preceding args and about the function being called. */
+-
+-static struct rtx_def *
+-_m68k_function_arg (CUMULATIVE_ARGS *, machine_mode, const_tree);
+-
+-static struct rtx_def *
+-_m68k_function_arg (CUMULATIVE_ARGS *cump, machine_mode mode, const_tree type)
+-{
+- struct amigaos_args * cum = &mycum;
+- DPRINTF(("m68k_function_arg numOfRegs=%d\r\n", cum ? cum->num_of_regs : 0));
+-
+- if (cump != lastcum)
+- return 0;
+-
+- if (cum->num_of_regs)
+- {
+- int regbegin = -1, altregbegin = -1, len;
+-
+- /* FIXME: The last condition below is a workaround for a bug. */
+- if (TARGET_68881 && FLOAT_MODE_P(mode) &&
+- GET_MODE_UNIT_SIZE (mode) <= 12
+- && (GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT || mode == SCmode))
+- {
+- regbegin = 16; /* FPx */
+- len = GET_MODE_NUNITS(mode);
+- }
+- /* FIXME: Two last conditions below are workarounds for bugs. */
+- else if (INTEGRAL_MODE_P (mode) && mode != CQImode && mode != CHImode)
+- {
+- if (!type || POINTER_TYPE_P(type))
+- regbegin = 8; /* Ax */
+- else
+- regbegin = 0; /* Dx */
+- altregbegin = 8 - regbegin;
+- len = (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
+- }
+-
+- if (regbegin != -1)
+- {
+- int reg;
+- long mask;
+-
+- look_for_reg: mask = 1 << regbegin;
+- for (reg = 0; reg < cum->num_of_regs; reg++, mask <<= 1)
+- if (!(cum->regs_already_used & mask))
+- {
+- int end;
+- for (end = reg; end < cum->num_of_regs && end < reg + len;
+- end++, mask <<= 1)
+- if (cum->regs_already_used & mask)
+- break;
+- if (end == reg + len)
+- {
+- cum->last_arg_reg = reg + regbegin;
+- cum->last_arg_len = len;
+- break;
+- }
+- }
+-
+- if (reg == AMIGAOS_MAX_REGPARM && altregbegin != -1)
+- {
+- DPRINTF(("look for alt reg\n"));
+- regbegin = altregbegin;
+- altregbegin = -1;
+- goto look_for_reg;
+- }
+- }
+-
+- if (cum->last_arg_reg != -1)
+- {
+- DPRINTF(("-> gen_rtx_REG %d\r\n", cum->last_arg_reg));
+- return gen_rtx_REG (mode, cum->last_arg_reg);
+- }
+- }
+- return 0;
+-}
+-
+-/* A C expression that controls whether a function argument is passed
+- in a register, and which register. */
+-
+-struct rtx_def *
+-amigaos_function_arg (cumulative_args_t cum_v, machine_mode mode,
+- const_tree type, bool)
+-{
+- struct amigaos_args * cum = &mycum;
+-
+- DPRINTF(("amigaos_function_arg %p\r\n", cum_v.p));
+-
+- CUMULATIVE_ARGS *cump = (CUMULATIVE_ARGS *) get_cumulative_args (cum_v);
+-
+- if (cump != lastcum)
+- return 0;
+-
+- tree asmtree = type ? TYPE_ATTRIBUTES(type) : NULL_TREE;
+- if (asmtree && 0 == strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(asmtree))))
+- {
+- int i;
+- cum->last_arg_reg = TREE_FIXED_CST_PTR(TREE_VALUE(asmtree))->data.low;
+- cum->last_arg_len = HARD_REGNO_NREGS(cum->last_arg_reg, mode);
+-
+- for (i = 0; i < cum->last_arg_len; i++)
+- if (cum->regs_already_used & (1 << (cum->last_arg_reg + i)))
+- {
+- error ("two parameters allocated for one register");
+- break;
+- }
+- return gen_rtx_REG (mode, cum->last_arg_reg);
+- }
+- return _m68k_function_arg (cump, mode, type);
+-}
+-
+-/* Return zero if the attributes on TYPE1 and TYPE2 are incompatible,
+- one if they are compatible, and two if they are nearly compatible
+- (which causes a warning to be generated). */
+-
+-int
+-amigaos_comp_type_attributes (const_tree type1, const_tree type2)
+-{
+- DPRINTF(("amigaos_comp_type_attributes\n"));
+- /* Functions or methods are incompatible if they specify mutually exclusive
+- ways of passing arguments. */
+- if (TREE_CODE(type1) == FUNCTION_TYPE || TREE_CODE(type1) == METHOD_TYPE)
+- {
+- tree arg1, arg2;
+- arg1 = TYPE_ARG_TYPES(type1);
+- arg2 = TYPE_ARG_TYPES(type2);
+- for (; arg1 && arg2; arg1 = TREE_CHAIN(arg1), arg2 = TREE_CHAIN(arg2))
+- {
+- tree attr1 = TYPE_ATTRIBUTES(arg1);
+- tree attr2 = TYPE_ATTRIBUTES(arg2);
+- if (strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(attr1))))
+- attr1 = NULL_TREE;
+- if (strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(attr2))))
+- attr2 = NULL_TREE;
+- if (attr1 && attr2)
+- {
+- if (TREE_FIXED_CST_PTR(TREE_VALUE(attr1))->data.low
+- != TREE_FIXED_CST_PTR(TREE_VALUE(attr2))->data.low)
+- return 0;
+- }
+- else if (attr1 || attr2)
+- return 0; /* asm attribute only on one side. */
+- }
+- if (arg1 || arg2)
+- return 0; /* different count of parameters. */
+- }
+- return 1;
+-}
+-
+-/* Return zero if the attributes on TYPE1 and TYPE2 are incompatible,
+- one if they are compatible, and two if they are nearly compatible
+- (which causes a warning to be generated). */
+-#if 0
+-static int
+-m68k_comp_type_attributes (tree type1, tree type2)
+-{
+-
+- /* Functions or methods are incompatible if they specify mutually
+- exclusive ways of passing arguments. */
+- if (TREE_CODE (type1) == FUNCTION_TYPE || TREE_CODE (type1) == METHOD_TYPE)
+- {
+- tree arg1, arg2;
+- if (!! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type1)) !=
+- !! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type2))
+- || !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1)) !=
+- !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2)))
+- return 0; /* 'regparm' and 'stkparm' are mutually exclusive. */
+-
+- arg1 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1));
+- arg2 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2));
+- if (arg1 && arg2)
+- {
+- int num1 = 0, num2 = 0;
+- if (TREE_VALUE (arg1) && TREE_CODE (TREE_VALUE (arg1)) == TREE_LIST)
+- {
+- tree numofregs = TREE_VALUE (TREE_VALUE (arg1));
+- if (numofregs)
+- num1 = TREE_INT_CST_LOW (numofregs);
+- }
+- if (TREE_VALUE (arg2) && TREE_CODE (TREE_VALUE (arg2)) == TREE_LIST)
+- {
+- tree numofregs = TREE_VALUE (TREE_VALUE (arg2));
+- if (numofregs)
+- num2 = TREE_INT_CST_LOW (numofregs);
+- }
+- if (num1 != num2)
+- return 0; /* Different numbers, or no number in one type. */
+- }
+- }
+-#ifdef TARGET_AMIGAOS
+- return amigaos_comp_type_attributes(type1, type2);
+-#else
+- return 1;
+-#endif
+-}
+-#endif
+-
+-/* end-GG-local */
+-
+-
+-/* Handle a "regparm", "stkparm" attribute;
+- arguments as in struct attribute_spec.handler. */
+-tree
+-amigaos_handle_type_attribute (tree *node, tree name, tree args,
+- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+-{
+- tree nnn = *node;
+- do { // while (0);
+- DPRINTF(("%p with treecode %d\n", node, TREE_CODE(nnn)));
+- if (TREE_CODE (nnn) == FUNCTION_DECL || TREE_CODE (nnn) == FUNCTION_TYPE
+- || TREE_CODE (nnn) == METHOD_TYPE)
+- {
+- /* 'regparm' accepts one optional argument - number of registers in
+- single class that should be used to pass arguments. */
+- if (is_attribute_p ("regparm", name))
+- {
+- DPRINTF(("regparm found\n"));
+-
+- if (lookup_attribute ("stkparm", TYPE_ATTRIBUTES(nnn)))
+- {
+- error ("`regparm' and `stkparm' are mutually exclusive");
+- break;
+- }
+- if (args && TREE_CODE (args) == TREE_LIST)
+- {
+- tree val = TREE_VALUE(args);
+- DPRINTF(("regparm with val: %d\n", TREE_CODE(val)));
+- if (TREE_CODE (val) == INTEGER_CST)
+- {
+- int no = TREE_INT_CST_LOW(val);
+- if (no < 0 || no > AMIGAOS_MAX_REGPARM)
+- {
+- error ("`regparm' attribute: value %d not in [0 - %d]",
+- no,
+- AMIGAOS_MAX_REGPARM);
+- break;
+- }
+- }
+- else
+- {
+- error ("invalid argument(s) to `regparm' attribute");
+- break;
+- }
+- }
+- }
+- else if (is_attribute_p ("stkparm", name))
+- {
+- if (lookup_attribute ("regparm", TYPE_ATTRIBUTES(nnn)))
+- {
+- error ("`regparm' and `stkparm' are mutually exclusive");
+- break;
+- }
+- }
+- else if (is_attribute_p ("stackext", name))
+- {
+- if (lookup_attribute ("interrupt", TYPE_ATTRIBUTES(nnn)))
+- {
+- error ("`stackext' and `interrupt' are mutually exclusive");
+- break;
+- }
+- }
+- else if (is_attribute_p ("saveds", name))
+- {
+- }
+- }
+- else
+- {
+- warning (OPT_Wattributes, "`%s' attribute only applies to functions",
+- IDENTIFIER_POINTER(name));
+- }
+- return NULL_TREE;
+- } while (0);
+- // error case
+- *no_add_attrs = true;
+- return NULL_TREE;
+-}
+-
+-
+-extern bool
+-m68k_rtx_costs (rtx, machine_mode, int, int, int *, bool);
+-
+-bool
+-amigaos_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno,
+- int *total, bool speed)
+-{
+-// DPRINTF(("outer: %d, opno: %d", outer_code, opno));
+- bool r = m68k_rtx_costs (x, mode, outer_code, opno, total, speed);
+-// *total *= 4;
+-// fprintf(stderr, "costs: %d, mode=%d, outer=%d, opno=%d, speed=%d, ok=%d\n", *total * 4, mode, outer_code, opno, speed, r);
+-// debug_rtx(x);
+- return r;
+-}
+-
+-
+-/* Output assembly to switch to section NAME with attribute FLAGS. */
+-
+-extern void
+-amiga_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_UNUSED)
+-{
+- if (0 == strncmp(".text", name, 5))
+- name = ".text";
+- fprintf (asm_out_file, "\t%s\n", name);
+-}
+-
+-/* Baserel support. */
+-
+-/**
+- * Does x reference the pic_reg and is const or plus?
+- */
+-int amiga_is_const_pic_ref(const_rtx x)
+-{
+- const_rtx y = x;
+- if (flag_pic < 3)
+- return false;
+- while (GET_CODE(y) == CONST || GET_CODE(y) == PLUS)
+- y = XEXP(y, 0);
+- return (x != y && REG_P(y) && REGNO(y) == PIC_REG);
+-}
+-
+-
+-/* Does operand (which is a symbolic_operand) live in text space? If
+- so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true.
+-
+- This function is used in base relative code generation. */
+-
+-int
+-read_only_operand (rtx operand)
+-{
+- if (GET_CODE (operand) == CONST)
+- operand = XEXP (XEXP (operand, 0), 0);
+- if (GET_CODE (operand) == SYMBOL_REF)
+- return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand);
+- return 1;
+-}
+-
+-reg_class_t
+-amiga_preferred_rename_class2(reg_class_t rclass ATTRIBUTE_UNUSED, int regno )
+-{
+- if (regno == 0)
+- return D0_REGS;
+- if (regno == 8)
+- return A0_REGS;
+- return regno_reg_class[regno];
+-}
++/* Configuration for GNU C-compiler for m68k Amiga, running AmigaOS.
++ Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2003
++ Free Software Foundation, Inc.
++ Contributed by Markus M. Wild (wild@amiga.physik.unizh.ch).
++ Heavily modified by Kamil Iskra (iskra@student.uci.agh.edu.pl).
++
++This file is part of GCC.
++
++GCC 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.
++
++GCC 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 GCC; see the file COPYING. If not, write to
++the Free Software Foundation, 59 Temple Place - Suite 330,
++Boston, MA 02111-1307, USA. */
++
++//work without flag_writable_strings which is not in GCC4
++#define REGPARMS_68K 1
++
++#include "config.h"
++#include "system.h"
++#include "coretypes.h"
++#include "tm.h"
++#include "rtl.h"
++#include "output.h"
++#include "tree.h"
++#include "attribs.h"
++#include "flags.h"
++#include "expr.h"
++#include "toplev.h"
++#include "tm_p.h"
++#include "target.h"
++#include "diagnostic-core.h"
++#include "config/m68k/amigaos.h"
++
++//#define MYDEBUG 1
++#ifdef MYDEBUG
++#define DPRINTF(x) printf x; fflush(stdout);
++#else
++#define DPRINTF(x)
++#endif
++
++//int amiga_declare_object;
++
++#if 0
++static int amigaos_put_in_text (tree);
++static rtx gen_stack_management_call (rtx, rtx, const char *);
++
++/* Baserel support. */
++
++/* Does operand (which is a symbolic_operand) live in text space? If
++ so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true.
++
++ This function is used in base relative code generation. */
++
++int
++read_only_operand (rtx operand)
++{
++ if (GET_CODE (operand) == CONST)
++ operand = XEXP (XEXP (operand, 0), 0);
++ if (GET_CODE (operand) == SYMBOL_REF)
++ return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand);
++ return 1;
++}
++
++/* Choose the section to use for DECL. RELOC is true if its value contains
++ any relocatable expression. */
++
++void
++amigaos_select_section (tree decl ATTRIBUTE_UNUSED, int reloc ATTRIBUTE_UNUSED,
++ unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
++{
++ // if (TREE_CODE (decl) == STRING_CST)
++// {
++//// flag_writable_strings /data_section not in gcc4,
++////make life easy and put to same section
++//// if (! flag_writable_strings)
++//// readonly_data_section ();
++//// else
++// //data_section ();
++// }
++// else if (TREE_CODE (decl) == VAR_DECL)
++// {
++// if (TREE_READONLY (decl)
++// && ! TREE_THIS_VOLATILE (decl)
++// && DECL_INITIAL (decl)
++// && (DECL_INITIAL (decl) == error_mark_node
++// || TREE_CONSTANT (DECL_INITIAL (decl)))
++// && (!flag_pic || (flag_pic<3 && !reloc)
++// || SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0))))
++// readonly_data_section ();
++// else
++// data_section ();
++// }
++// else if ((!flag_pic || (flag_pic<3 && !reloc)) && DECL_P(decl)
++// && SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)))
++// readonly_data_section ();
++// else
++ //data_section ();
++}
++
++/* This function is used while generating a base relative code.
++ It returns 1 if a decl is not relocatable, i. e., if it can be put
++ in the text section.
++ Currently, it's very primitive: it just checks if the object size
++ is less than 4 bytes (i. e., if it can hold a pointer). It also
++ supports arrays and floating point types. */
++
++static int
++amigaos_put_in_text (tree decl)
++{
++ tree type = TREE_TYPE (decl);
++ if (TREE_CODE (type) == ARRAY_TYPE)
++ type = TREE_TYPE (type);
++ return (TREE_INT_CST_ELT(TYPE_SIZE (type), 1) == 0
++ && TREE_INT_CST_LOW (TYPE_SIZE (type)) < 32)
++ || FLOAT_TYPE_P (type);
++}
++
++/* Record properties of a DECL into the associated SYMBOL_REF. */
++
++void
++amigaos_encode_section_info (tree decl, rtx rtl, int first)
++{
++ default_encode_section_info (decl, rtl, first);
++
++
++ SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
++ if (TREE_CODE (decl) == FUNCTION_DECL) // huh seem do same. not in gcc4 flag_writable_strings
++ SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
++ else
++ {
++ if ((MEM_READONLY_P (rtl) && !MEM_VOLATILE_P (rtl)
++ && (flag_pic<3 || (TREE_CODE (decl) == STRING_CST
++ )
++ || amigaos_put_in_text (decl)))
++ || (TREE_CODE (decl) == VAR_DECL
++ && DECL_SECTION_NAME (decl) != NULL))
++ SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
++ }
++}
++
++/* Common routine used to check if a4 should be preserved/restored. */
++
++int
++amigaos_restore_a4 (void)
++{
++ return (flag_pic >= 3 &&
++ (TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4
++ || lookup_attribute ("saveds",
++ TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))));
++}
++
++void
++amigaos_alternate_pic_setup (FILE *stream)
++{
++ if (TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4)
++ asm_fprintf (stream, "\tjbsr %U__restore_a4\n");
++ else if (lookup_attribute ("saveds",
++ TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
++ asm_fprintf (stream, "\tlea %U__a4_init,%Ra4\n");
++}
++
++/* Attributes support. */
++
++#define AMIGA_CHIP_SECTION_NAME ".datachip"
++
++/* Handle a "chip" attribute;
++ arguments as in struct attribute_spec.handler. */
++
++tree
++amigaos_handle_decl_attribute (tree *node, tree name,
++ tree args ATTRIBUTE_UNUSED,
++ int flags ATTRIBUTE_UNUSED,
++ bool *no_add_attrs)
++{
++ if (TREE_CODE (*node) == VAR_DECL)
++ {
++ if (is_attribute_p ("chip", name))
++#ifdef TARGET_ASM_NAMED_SECTION
++ {
++ if (! TREE_STATIC (*node) && ! DECL_EXTERNAL (*node))
++ error ("`chip' attribute cannot be specified for local variables");
++ else
++ {
++ /* The decl may have already been given a section attribute from
++ a previous declaration. Ensure they match. */
++ if (DECL_SECTION_NAME (*node) == NULL_TREE)
++ DECL_SECTION_NAME (*node) =
++ build_string (strlen (AMIGA_CHIP_SECTION_NAME) + 1,
++ AMIGA_CHIP_SECTION_NAME);
++ else if (strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (*node)),
++ AMIGA_CHIP_SECTION_NAME) != 0)
++ {
++ error_with_decl (*node,
++ "`chip' for `%s' conflicts with previous declaration");
++ }
++ }
++ }
++#else
++ error ("`chip' attribute is not supported for this target");
++#endif
++ }
++ else
++ {
++ warning (OPT_Wattributes, "`%s' attribute only applies to variables",
++ IDENTIFIER_POINTER (name));
++ *no_add_attrs = true;
++ }
++
++ return NULL_TREE;
++}
++
++//----- from 68k.c start
++
++
++
++
++
++
++/* Stack checking and automatic extension support. */
++
++void
++amigaos_prologue_begin_hook (FILE *stream, int fsize)
++{
++ if (TARGET_STACKCHECK)
++ {
++ if (fsize < 256)
++ asm_fprintf (stream, "\tcmpl %s,%Rsp\n"
++ "\tjcc 0f\n"
++ "\tjra %U__stkovf\n"
++ "\t0:\n",
++ (flag_pic == 3 ? "a4@(___stk_limit:W)" :
++ (flag_pic == 4 ? "a4@(___stk_limit:L)" :
++ "___stk_limit")));
++ else
++ asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__stkchk_d0\n",
++ fsize);
++ }
++}
++
++void
++amigaos_alternate_frame_setup_f (FILE *stream, int fsize)
++{
++ if (fsize < 128)
++ asm_fprintf (stream, "\tcmpl %s,%Rsp\n"
++ "\tjcc 0f\n"
++ "\tmoveq %I%d,%Rd0\n"
++ "\tmoveq %I0,%Rd1\n"
++ "\tjbsr %U__stkext_f\n"
++ "0:\tlink %Ra5,%I%d:W\n",
++ (flag_pic == 3 ? "a4@(___stk_limit:W)" :
++ (flag_pic == 4 ? "a4@(___stk_limit:L)" :
++ "___stk_limit")),
++ fsize, -fsize);
++ else
++ asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__link_a5_d0_f\n",
++ fsize);
++}
++
++void
++amigaos_alternate_frame_setup (FILE *stream, int fsize)
++{
++ if (!fsize)
++ asm_fprintf (stream, "\tcmpl %s,%Rsp\n"
++ "\tjcc 0f\n"
++ "\tmoveq %I0,%Rd0\n"
++ "\tmoveq %I0,%Rd1\n"
++ "\tjbsr %U__stkext_f\n"
++ "0:\n",
++ (flag_pic == 3 ? "a4@(___stk_limit:W)" :
++ (flag_pic == 4 ? "a4@(___stk_limit:L)" :
++ "___stk_limit")));
++ else if (fsize < 128)
++ asm_fprintf (stream, "\tcmpl %s,%Rsp\n"
++ "\tjcc 0f\n"
++ "\tmoveq %I%d,%Rd0\n"
++ "\tmoveq %I0,%Rd1\n"
++ "\tjbsr %U__stkext_f\n"
++ "0:\taddw %I%d,%Rsp\n",
++ (flag_pic == 3 ? "a4@(___stk_limit:W)" :
++ (flag_pic == 4 ? "a4@(___stk_limit:L)" :
++ "___stk_limit")),
++ fsize, -fsize);
++ else
++ asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__sub_d0_sp_f\n",
++ fsize);
++}
++
++//static rtx
++//gen_stack_management_call (rtx stack_pointer, rtx arg, const char *func)
++//{
++// rtx call_insn, call, seq, name;
++// start_sequence ();
++//
++// /* Move arg to d0. */
++// emit_move_insn (gen_rtx_REG (SImode, 0), arg);
++//
++// /* Generate the function reference. */
++// name = gen_rtx_SYMBOL_REF (Pmode, func);
++// SYMBOL_REF_FLAG (name) = 1;
++// /* If optimizing, put it in a psedo so that several loads can be merged
++// into one. */
++// if (optimize && ! flag_no_function_cse)
++// name = copy_to_reg (name);
++//
++// /* Generate the function call. */
++// call = gen_rtx_CALL (VOIDmode, gen_rtx_MEM (FUNCTION_MODE, name),
++// const0_rtx);
++// /* If we are doing stack extension, notify about the sp change. */
++// if (stack_pointer)
++// call = gen_rtx_SET (VOIDmode, stack_pointer, call);
++//
++// /* Generate the call instruction. */
++// call_insn = emit_call_insn (call);
++// /* Stack extension does not change memory in an unpredictable way. */
++// RTL_CONST_OR_PURE_CALL_P (call_insn) = 1;
++// /* We pass an argument in d0. */
++// CALL_INSN_FUNCTION_USAGE (call_insn) = gen_rtx_EXPR_LIST (VOIDmode,
++// gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, 0)), 0);
++//
++// seq = get_insns ();
++// end_sequence ();
++// return seq;
++//}
++//
++//rtx
++//gen_stack_cleanup_call (rtx stack_pointer, rtx sa)
++//{
++// return gen_stack_management_call (stack_pointer, sa, "__move_d0_sp");
++//}
++//
++//void
++//amigaos_alternate_allocate_stack (rtx *operands)
++//{
++// if (TARGET_STACKEXTEND)
++// emit_insn (gen_stack_management_call (stack_pointer_rtx, operands[1],
++// "__sub_d0_sp"));
++// else
++// {
++// if (TARGET_STACKCHECK)
++// emit_insn (gen_stack_management_call (0, operands[1], "__stkchk_d0"));
++// anti_adjust_stack (operands[1]);
++// }
++// emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
++//}
++#endif
++
++/*
++ * begin-GG-local: explicit register specification for parameters.
++ *
++ * Reworked and ported to gcc-6.2.0 by Stefan "Bebbo" Franke.
++ */
++
++/**
++ * Define this here and add it to tm_p -> all know the custom type and allocate/use the correct size.
++ */
++struct amigaos_args
++{
++ int num_of_regs;
++ long regs_already_used;
++ int last_arg_reg;
++ int last_arg_len;
++ tree formal_type; /* New field: formal type of the current argument. */
++};
++
++static struct amigaos_args mycum, othercum;
++
++/* Argument-passing support functions. */
++
++/* Initialize a variable CUM of type CUMULATIVE_ARGS
++ for a call to a function whose data type is FNTYPE.
++ For a library call, FNTYPE is 0. */
++
++void
++amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl)
++{
++ struct amigaos_args * cum = decl == current_function_decl ? &mycum : &othercum;
++ *cump = (int)cum;
++ cum->num_of_regs = amigaos_regparm > 0 ? amigaos_regparm : 0;
++ DPRINTF(("0amigaos_init_cumulative_args %p -> %d\r\n", cum, cum->num_of_regs));
++
++ /* Initialize a variable CUM of type CUMULATIVE_ARGS
++ for a call to a function whose data type is FNTYPE.
++ For a library call, FNTYPE is 0. */
++
++ cum->last_arg_reg = -1;
++ cum->regs_already_used = 0;
++
++ if (decl)
++ {
++ tree attrs = DECL_ATTRIBUTES(decl);
++ if (lookup_attribute ("stkparm", attrs))
++ cum->num_of_regs = 0;
++ else
++ {
++ tree ratree = lookup_attribute ("regparm", attrs);
++ cum->num_of_regs = amigaos_regparm != 0 ?
++ amigaos_regparm : AMIGAOS_DEFAULT_REGPARM;
++ if (ratree)
++ {
++ tree args = TREE_VALUE(ratree);
++
++ if (args && TREE_CODE (args) == TREE_LIST)
++ {
++ tree val = TREE_VALUE(args);
++ if (TREE_CODE (val) == INTEGER_CST)
++ {
++ int no = TREE_INT_CST_LOW(val);
++ if (no > 0 && no < AMIGAOS_MAX_REGPARM)
++ cum->num_of_regs = no;
++ }
++ }
++ }
++ }
++ }
++ else
++ /* Libcall. */
++ cum->num_of_regs = 0;
++
++ if (cum->num_of_regs)
++ {
++ /* If this is a vararg call, put all arguments on stack. */
++ tree param, next_param;
++ for (param = TYPE_ARG_TYPES(fntype); param; param = next_param)
++ {
++ next_param = TREE_CHAIN(param);
++ if (!next_param && TREE_VALUE (param) != void_type_node)
++ cum->num_of_regs = 0;
++ }
++ }
++
++ //#if ! defined (PCC_STATIC_STRUCT_RETURN) && defined (M68K_STRUCT_VALUE_REGNUM)
++ // /* If return value is a structure, and we pass the buffer address in a
++ // register, we can't use this register for our own purposes.
++ // FIXME: Something similar would be useful for static chain. */
++ // if (fntype && aggregate_value_p (TREE_TYPE (fntype), fntype))
++ // cum->regs_already_used |= (1 << M68K_STRUCT_VALUE_REGNUM);
++ //#endif
++
++ if (fntype)
++ cum->formal_type = TYPE_ARG_TYPES(fntype);
++ else
++ /* Call to compiler-support function. */
++ cum->formal_type = 0;
++ DPRINTF(("1amigaos_init_cumulative_args %p -> %d\r\n", cum, cum->num_of_regs));
++}
++
++/* Update the data in CUM to advance over an argument. */
++
++void
++amigaos_function_arg_advance (cumulative_args_t cum_v, machine_mode, const_tree,
++ bool)
++{
++ struct amigaos_args *cum = *(struct amigaos_args **) get_cumulative_args (cum_v);
++ /* Update the data in CUM to advance over an argument. */
++
++ DPRINTF(("amigaos_function_arg_advance1 %p\r\n", cump));
++
++ if (cum->last_arg_reg != -1)
++ {
++ int count;
++ for (count = 0; count < cum->last_arg_len; count++)
++ cum->regs_already_used |= (1 << (cum->last_arg_reg + count));
++ cum->last_arg_reg = -1;
++ }
++
++ if (cum->formal_type)
++ cum->formal_type = TREE_CHAIN(cum->formal_type);
++}
++
++/* Define where to put the arguments to a function.
++ Value is zero to push the argument on the stack,
++ or a hard register in which to store the argument.
++
++ MODE is the argument's machine mode.
++ TYPE is the data type of the argument (as a tree).
++ This is null for libcalls where that information may
++ not be available.
++ CUM is a variable of type CUMULATIVE_ARGS which gives info about
++ the preceding args and about the function being called. */
++
++static struct rtx_def *
++_m68k_function_arg (CUMULATIVE_ARGS *, machine_mode, const_tree);
++
++static struct rtx_def *
++_m68k_function_arg (struct amigaos_args * cum, machine_mode mode, const_tree type)
++{
++ DPRINTF(("m68k_function_arg numOfRegs=%d\r\n", cum ? cum->num_of_regs : 0));
++
++ if (cum->num_of_regs)
++ {
++ int regbegin = -1, altregbegin = -1, len;
++
++ /* FIXME: The last condition below is a workaround for a bug. */
++ if (TARGET_68881 && FLOAT_MODE_P(mode) &&
++ GET_MODE_UNIT_SIZE (mode) <= 12
++ && (GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT || mode == SCmode))
++ {
++ regbegin = 16; /* FPx */
++ len = GET_MODE_NUNITS(mode);
++ }
++ /* FIXME: Two last conditions below are workarounds for bugs. */
++ else if (INTEGRAL_MODE_P (mode) && mode != CQImode && mode != CHImode)
++ {
++ if (!type || POINTER_TYPE_P(type))
++ regbegin = 8; /* Ax */
++ else
++ regbegin = 0; /* Dx */
++ altregbegin = 8 - regbegin;
++ len = (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
++ }
++
++ if (regbegin != -1)
++ {
++ int reg;
++ long mask;
++
++ look_for_reg: mask = 1 << regbegin;
++ for (reg = 0; reg < cum->num_of_regs; reg++, mask <<= 1)
++ if (!(cum->regs_already_used & mask))
++ {
++ int end;
++ for (end = reg; end < cum->num_of_regs && end < reg + len;
++ end++, mask <<= 1)
++ if (cum->regs_already_used & mask)
++ break;
++ if (end == reg + len)
++ {
++ cum->last_arg_reg = reg + regbegin;
++ cum->last_arg_len = len;
++ break;
++ }
++ }
++
++ if (reg == AMIGAOS_MAX_REGPARM && altregbegin != -1)
++ {
++ DPRINTF(("look for alt reg\n"));
++ regbegin = altregbegin;
++ altregbegin = -1;
++ goto look_for_reg;
++ }
++ }
++
++ if (cum->last_arg_reg != -1)
++ {
++ DPRINTF(("-> gen_rtx_REG %d\r\n", cum->last_arg_reg));
++ return gen_rtx_REG (mode, cum->last_arg_reg);
++ }
++ }
++ return 0;
++}
++
++/* A C expression that controls whether a function argument is passed
++ in a register, and which register. */
++
++struct rtx_def *
++amigaos_function_arg (cumulative_args_t cum_v, machine_mode mode,
++ const_tree type, bool)
++{
++ DPRINTF(("amigaos_function_arg %p\r\n", cum_v.p));
++
++ struct amigaos_args *cum = *(struct amigaos_args **) get_cumulative_args (cum_v);
++
++ tree asmtree = type ? TYPE_ATTRIBUTES(type) : NULL_TREE;
++ if (asmtree && 0 == strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(asmtree))))
++ {
++ int i;
++ cum->last_arg_reg = TREE_FIXED_CST_PTR(TREE_VALUE(asmtree))->data.low;
++ cum->last_arg_len = HARD_REGNO_NREGS(cum->last_arg_reg, mode);
++
++ for (i = 0; i < cum->last_arg_len; i++)
++ {
++ if (cum->regs_already_used & (1 << (cum->last_arg_reg + i)))
++ {
++ error ("two parameters allocated for one register");
++ break;
++ }
++ cum->regs_already_used |= (1 << (cum->last_arg_reg + i));
++ }
++ return gen_rtx_REG (mode, cum->last_arg_reg);
++ }
++ return _m68k_function_arg (cum, mode, type);
++}
++
++void amiga_emit_regparm_clobbers(void)
++{
++ int x = 0;
++ for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
++ {
++ if (mycum.regs_already_used & (1 << i))
++ emit_insn(gen_rtx_CLOBBER(Pmode, gen_raw_REG(Pmode, i)));
++ }
++}
++
++
++/* Return zero if the attributes on TYPE1 and TYPE2 are incompatible,
++ one if they are compatible, and two if they are nearly compatible
++ (which causes a warning to be generated). */
++
++int
++amigaos_comp_type_attributes (const_tree type1, const_tree type2)
++{
++ DPRINTF(("amigaos_comp_type_attributes\n"));
++ /* Functions or methods are incompatible if they specify mutually exclusive
++ ways of passing arguments. */
++ if (TREE_CODE(type1) == FUNCTION_TYPE || TREE_CODE(type1) == METHOD_TYPE)
++ {
++ tree arg1, arg2;
++ arg1 = TYPE_ARG_TYPES(type1);
++ arg2 = TYPE_ARG_TYPES(type2);
++ for (; arg1 && arg2; arg1 = TREE_CHAIN(arg1), arg2 = TREE_CHAIN(arg2))
++ {
++ tree attr1 = TYPE_ATTRIBUTES(arg1);
++ tree attr2 = TYPE_ATTRIBUTES(arg2);
++ if (strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(attr1))))
++ attr1 = NULL_TREE;
++ if (strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(attr2))))
++ attr2 = NULL_TREE;
++ if (attr1 && attr2)
++ {
++ if (TREE_FIXED_CST_PTR(TREE_VALUE(attr1))->data.low
++ != TREE_FIXED_CST_PTR(TREE_VALUE(attr2))->data.low)
++ return 0;
++ }
++ else if (attr1 || attr2)
++ return 0; /* asm attribute only on one side. */
++ }
++ if (arg1 || arg2)
++ return 0; /* different count of parameters. */
++ }
++ return 1;
++}
++
++/* Return zero if the attributes on TYPE1 and TYPE2 are incompatible,
++ one if they are compatible, and two if they are nearly compatible
++ (which causes a warning to be generated). */
++#if 0
++static int
++m68k_comp_type_attributes (tree type1, tree type2)
++{
++
++ /* Functions or methods are incompatible if they specify mutually
++ exclusive ways of passing arguments. */
++ if (TREE_CODE (type1) == FUNCTION_TYPE || TREE_CODE (type1) == METHOD_TYPE)
++ {
++ tree arg1, arg2;
++ if (!! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type1)) !=
++ !! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type2))
++ || !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1)) !=
++ !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2)))
++ return 0; /* 'regparm' and 'stkparm' are mutually exclusive. */
++
++ arg1 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1));
++ arg2 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2));
++ if (arg1 && arg2)
++ {
++ int num1 = 0, num2 = 0;
++ if (TREE_VALUE (arg1) && TREE_CODE (TREE_VALUE (arg1)) == TREE_LIST)
++ {
++ tree numofregs = TREE_VALUE (TREE_VALUE (arg1));
++ if (numofregs)
++ num1 = TREE_INT_CST_LOW (numofregs);
++ }
++ if (TREE_VALUE (arg2) && TREE_CODE (TREE_VALUE (arg2)) == TREE_LIST)
++ {
++ tree numofregs = TREE_VALUE (TREE_VALUE (arg2));
++ if (numofregs)
++ num2 = TREE_INT_CST_LOW (numofregs);
++ }
++ if (num1 != num2)
++ return 0; /* Different numbers, or no number in one type. */
++ }
++ }
++#ifdef TARGET_AMIGAOS
++ return amigaos_comp_type_attributes(type1, type2);
++#else
++ return 1;
++#endif
++}
++#endif
++
++/* end-GG-local */
++
++
++/* Handle a "regparm", "stkparm" attribute;
++ arguments as in struct attribute_spec.handler. */
++tree
++amigaos_handle_type_attribute (tree *node, tree name, tree args,
++ int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
++{
++ tree nnn = *node;
++ do { // while (0);
++ DPRINTF(("%p with treecode %d\n", node, TREE_CODE(nnn)));
++ if (TREE_CODE (nnn) == FUNCTION_DECL || TREE_CODE (nnn) == FUNCTION_TYPE
++ || TREE_CODE (nnn) == METHOD_TYPE)
++ {
++ /* 'regparm' accepts one optional argument - number of registers in
++ single class that should be used to pass arguments. */
++ if (is_attribute_p ("regparm", name))
++ {
++ DPRINTF(("regparm found\n"));
++
++ if (lookup_attribute ("stkparm", TYPE_ATTRIBUTES(nnn)))
++ {
++ error ("`regparm' and `stkparm' are mutually exclusive");
++ break;
++ }
++ if (args && TREE_CODE (args) == TREE_LIST)
++ {
++ tree val = TREE_VALUE(args);
++ DPRINTF(("regparm with val: %d\n", TREE_CODE(val)));
++ if (TREE_CODE (val) == INTEGER_CST)
++ {
++ int no = TREE_INT_CST_LOW(val);
++ if (no < 0 || no > AMIGAOS_MAX_REGPARM)
++ {
++ error ("`regparm' attribute: value %d not in [0 - %d]",
++ no,
++ AMIGAOS_MAX_REGPARM);
++ break;
++ }
++ }
++ else
++ {
++ error ("invalid argument(s) to `regparm' attribute");
++ break;
++ }
++ }
++ }
++ else if (is_attribute_p ("stkparm", name))
++ {
++ if (lookup_attribute ("regparm", TYPE_ATTRIBUTES(nnn)))
++ {
++ error ("`regparm' and `stkparm' are mutually exclusive");
++ break;
++ }
++ }
++ else if (is_attribute_p ("stackext", name))
++ {
++ if (lookup_attribute ("interrupt", TYPE_ATTRIBUTES(nnn)))
++ {
++ error ("`stackext' and `interrupt' are mutually exclusive");
++ break;
++ }
++ }
++ else if (is_attribute_p ("saveds", name))
++ {
++ }
++ }
++ else
++ {
++ warning (OPT_Wattributes, "`%s' attribute only applies to functions",
++ IDENTIFIER_POINTER(name));
++ }
++ return NULL_TREE;
++ } while (0);
++ // error case
++ *no_add_attrs = true;
++ return NULL_TREE;
++}
++
++
++extern bool
++m68k_rtx_costs (rtx, machine_mode, int, int, int *, bool);
++
++bool
++amigaos_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno,
++ int *total, bool speed)
++{
++// DPRINTF(("outer: %d, opno: %d", outer_code, opno));
++ bool r = m68k_rtx_costs (x, mode, outer_code, opno, total, speed);
++// *total *= 4;
++// fprintf(stderr, "costs: %d, mode=%d, outer=%d, opno=%d, speed=%d, ok=%d\n", *total * 4, mode, outer_code, opno, speed, r);
++// debug_rtx(x);
++ return r;
++}
++
++
++/* Output assembly to switch to section NAME with attribute FLAGS. */
++
++extern void
++amiga_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_UNUSED)
++{
++ if (0 == strncmp(".text", name, 5))
++ name = ".text";
++ fprintf (asm_out_file, "\t%s\n", name);
++}
++
++/* Baserel support. */
++
++/**
++ * Does x reference the pic_reg and is const or plus?
++ */
++int amiga_is_const_pic_ref(const_rtx x)
++{
++ const_rtx y = x;
++ if (flag_pic < 3)
++ return false;
++ while (GET_CODE(y) == CONST || GET_CODE(y) == PLUS)
++ y = XEXP(y, 0);
++ return (x != y && REG_P(y) && REGNO(y) == PIC_REG);
++}
++
++
++/* Does operand (which is a symbolic_operand) live in text space? If
++ so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true.
++
++ This function is used in base relative code generation. */
++
++int
++read_only_operand (rtx operand)
++{
++ if (GET_CODE (operand) == CONST)
++ operand = XEXP (XEXP (operand, 0), 0);
++ if (GET_CODE (operand) == SYMBOL_REF)
++ return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand);
++ return 1;
++}
++
++reg_class_t
++amiga_preferred_rename_class2 (reg_class_t rclass ATTRIBUTE_UNUSED, int regno)
++{
++ if (regno == 0)
++ return D0_REGS;
++ if (regno == 8)
++ return A0_REGS;
++ return regno_reg_class[regno];
++}
+diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
+index 52eabeaafb23..3fabe00a678a 100644
+--- gcc/config/m68k/m68k.c
++++ gcc/config/m68k/m68k.c
+@@ -1004,6 +1004,8 @@ m68k_set_frame_related (rtx_insn *insn)
+
+ /* Emit RTL for the "prologue" define_expand. */
+
++extern void amiga_emit_regparm_clobbers(void);
++
+ void
+ m68k_expand_prologue (void)
+ {
+@@ -1012,6 +1014,10 @@ m68k_expand_prologue (void)
+
+ m68k_compute_frame_layout ();
+
++#ifdef TARGET_AMIGA
++ amiga_emit_regparm_clobbers();
++#endif
++
+ if (flag_stack_usage_info)
+ current_function_static_stack_size
+ = current_frame.size + current_frame.offset;
+
+From 9aabe6ab20a761ee0311e7f44fe8d32cc51fc5a2 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 19 Apr 2017 14:40:38 +0200
+Subject: [PATCH 071/303] @B fix for 64bit builds
+
+---
+ gcc/config/m68k/amigaos.c | 16 +++++-----------
+ 1 file changed, 5 insertions(+), 11 deletions(-)
+
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index ca8eea305345..cf96844ad8cd 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -383,7 +383,7 @@ void
+ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl)
+ {
+ struct amigaos_args * cum = decl == current_function_decl ? &mycum : &othercum;
+- *cump = (int)cum;
++ *cump = decl == current_function_decl;
+ cum->num_of_regs = amigaos_regparm > 0 ? amigaos_regparm : 0;
+ DPRINTF(("0amigaos_init_cumulative_args %p -> %d\r\n", cum, cum->num_of_regs));
+
+@@ -459,7 +459,7 @@ void
+ amigaos_function_arg_advance (cumulative_args_t cum_v, machine_mode, const_tree,
+ bool)
+ {
+- struct amigaos_args *cum = *(struct amigaos_args **) get_cumulative_args (cum_v);
++ struct amigaos_args *cum = *get_cumulative_args (cum_v) ? &mycum : &othercum;
+ /* Update the data in CUM to advance over an argument. */
+
+ DPRINTF(("amigaos_function_arg_advance1 %p\r\n", cump));
+@@ -487,9 +487,6 @@ amigaos_function_arg_advance (cumulative_args_t cum_v, machine_mode, const_tree,
+ CUM is a variable of type CUMULATIVE_ARGS which gives info about
+ the preceding args and about the function being called. */
+
+-static struct rtx_def *
+-_m68k_function_arg (CUMULATIVE_ARGS *, machine_mode, const_tree);
+-
+ static struct rtx_def *
+ _m68k_function_arg (struct amigaos_args * cum, machine_mode mode, const_tree type)
+ {
+@@ -567,7 +564,7 @@ amigaos_function_arg (cumulative_args_t cum_v, machine_mode mode,
+ {
+ DPRINTF(("amigaos_function_arg %p\r\n", cum_v.p));
+
+- struct amigaos_args *cum = *(struct amigaos_args **) get_cumulative_args (cum_v);
++ struct amigaos_args *cum = *get_cumulative_args (cum_v) ? &mycum : &othercum;
+
+ tree asmtree = type ? TYPE_ATTRIBUTES(type) : NULL_TREE;
+ if (asmtree && 0 == strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(asmtree))))
+@@ -592,12 +589,9 @@ amigaos_function_arg (cumulative_args_t cum_v, machine_mode mode,
+
+ void amiga_emit_regparm_clobbers(void)
+ {
+- int x = 0;
+ for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+- {
+- if (mycum.regs_already_used & (1 << i))
+- emit_insn(gen_rtx_CLOBBER(Pmode, gen_raw_REG(Pmode, i)));
+- }
++ if (mycum.regs_already_used & (1 << i))
++ emit_insn(gen_rtx_CLOBBER(Pmode, gen_raw_REG(Pmode, i)));
+ }
+
+
+
+From aad2b7a890503955a2a1aae5ab09f89ed1466769 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 19 Apr 2017 18:37:57 +0200
+Subject: [PATCH 072/303] @R mregparm is using old register usage conventions
+
+---
+ gcc/config/m68k/amigaos.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index cf96844ad8cd..09934f94c06d 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -537,7 +537,7 @@ _m68k_function_arg (struct amigaos_args * cum, machine_mode mode, const_tree typ
+ }
+ }
+
+- if (reg == AMIGAOS_MAX_REGPARM && altregbegin != -1)
++ if (reg == cum->num_of_regs && altregbegin != -1)
+ {
+ DPRINTF(("look for alt reg\n"));
+ regbegin = altregbegin;
+
+From 554f57921f19cad9583eb4f319e12710ab786ceb Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 19 Apr 2017 18:40:05 +0200
+Subject: [PATCH 073/303] @B ensure that clobbers for mregparm are not marked
+ as REG_DEAD
+
+---
+ gcc/bbb-opts.c | 43 ++++++++++++++++++++++++++++---------------
+ gcc/regrename.c | 28 ++++++++++++++++++++++++++--
+ 2 files changed, 54 insertions(+), 17 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 1b1863e9ae8f..2c19242512a2 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -325,20 +325,24 @@ dump_insns (char const * name, bool all)
+ }
+ for (unsigned i = 0; i < insns.size (); ++i)
+ {
+- insn_info & ii = infos[i];
+-
+ fprintf (stderr, "%d: ", i);
+
+- for (int j = 0; j < 8; ++j)
+- if (ii.is_use (j))
+- fprintf (stderr, ii.is_def (j) ? "*d%d " : "d%d ", j);
++ if (i < infos.size ())
++ {
++ insn_info & ii = infos[i];
++
++ for (int j = 0; j < 8; ++j)
++ if (ii.is_use (j))
++ fprintf (stderr, ii.is_def (j) ? "*d%d " : "d%d ", j);
+
+- for (int j = 8; j < 16; ++j)
+- if (ii.is_use (j))
+- fprintf (stderr, ii.is_def (j) ? "*a%d " : "a%d ", j - 8);
++ for (int j = 8; j < 16; ++j)
++ if (ii.is_use (j))
++ fprintf (stderr, ii.is_def (j) ? "*a%d " : "a%d ", j - 8);
+
+- if (ii.is_use (FIRST_PSEUDO_REGISTER))
+- fprintf (stderr, ii.is_def (FIRST_PSEUDO_REGISTER) ? "*cc " : "cc ");
++ if (ii.is_use (FIRST_PSEUDO_REGISTER))
++ fprintf (stderr, ii.is_def (FIRST_PSEUDO_REGISTER) ? "*cc " : "cc ");
++
++ }
+
+ fprintf (stderr, "\t");
+ debug_rtx (insns[i]);
+@@ -502,6 +506,14 @@ update_insn_infos (void)
+ continue;
+ }
+
++ if (GET_CODE (pattern) == CLOBBER ) {
++ /* mark regs as use and def */
++ insn_info ud;
++ ud.scan(pattern);
++ ud._def |= ud._use;
++ infos[pos] |= ud;
++ continue;
++ }
+ if (GET_CODE (pattern) != PARALLEL && GET_CODE (pattern) != CLOBBER && be_verbose)
+ {
+ fprintf (stderr, "##### ");
+@@ -882,7 +894,7 @@ opt_strcpy ()
+ src = XEXP(src, 1);
+
+ // if (CONST_INT_P(src) && INTVAL(src) == 0 && find_reg_note (insn, REG_DEAD, dst))
+- if (REG_P(dst) && CONST_INT_P(src) && INTVAL(src) == 0 && is_reg_dead(REGNO(dst), index))
++ if (REG_P(dst) && CONST_INT_P(src) && INTVAL(src) == 0 && is_reg_dead (REGNO(dst), index))
+ {
+ /* now check via NOTICE_UPDATE_CC*/
+ NOTICE_UPDATE_CC(PATTERN (reg2x), reg2x);
+@@ -1300,7 +1312,7 @@ merge_add (void)
+
+ log ("merge_add applied\n");
+
+- rtx_insn * newins1 = make_insn_raw(gen_rtx_SET(dst1, l1));
++ rtx_insn * newins1 = make_insn_raw (gen_rtx_SET(dst1, l1));
+ add_insn_after (newins1, ins1, 0);
+ SET_INSN_DELETED(ins1);
+
+@@ -1836,9 +1848,9 @@ namespace
+ class opt_pass * rr = ::global_pass_regrename->clone ();
+ rr->execute (0);
+
+- // update_insns ();
+- // update_insn_infos ();
+- // bb_reg_rename ();
++ // update_insns ();
++ // update_insn_infos ();
++ // bb_reg_rename ();
+
+ update_insns ();
+ }
+@@ -1851,6 +1863,7 @@ namespace
+ {
+ shrink_stack_frame ();
+ update_insns ();
++ update_insn_infos ();
+ }
+
+ if (strchr (string_bbb_opts, 'X') || strchr (string_bbb_opts, 'x'))
+diff --git a/gcc/regrename.c b/gcc/regrename.c
+index 696e5557780e..eceb7286e31e 100755
+--- gcc/regrename.c
++++ gcc/regrename.c
+@@ -892,7 +892,7 @@ regrename_analyze (bitmap bb_mask)
+ if (!range_overlaps_hard_reg_set_p (live, chain->regno,
+ chain->nregs))
+ continue;
+-
++
+ n_succs_used++;
+
+ dest_ri = (struct bb_rename_info *)e->dest->aux;
+@@ -916,7 +916,7 @@ regrename_analyze (bitmap bb_mask)
+ printed = true;
+ fprintf (dump_file,
+ " merging chains %d (->%d) and %d (->%d) [%s]\n",
+- k, incoming_chain->id, j, chain->id,
++ k, incoming_chain->id, j, chain->id,
+ reg_names[incoming_chain->regno]);
+ }
+
+@@ -1892,6 +1892,28 @@ regrename_finish (void)
+ obstack_free (&rename_obstack, NULL);
+ }
+
++void
++mark_early_clobbers_alive (void)
++{
++ rtx_insn * insn;
++ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
++ {
++ rtx pattern;
++ if (NOTE_P(insn) && NOTE_KIND(insn) == NOTE_INSN_PROLOGUE_END)
++ break;
++
++ pattern = PATTERN (insn);
++ if (pattern && GET_CODE(pattern) == CLOBBER)
++ {
++ rtx *loc;
++
++ loc = &REG_NOTES(insn);
++ while (*loc)
++ *loc = XEXP(*loc, 1);
++ }
++ }
++}
++
+ /* Perform register renaming on the current function. */
+
+ static unsigned int
+@@ -1902,6 +1924,8 @@ regrename_optimize (void)
+ df_analyze ();
+ df_set_flags (DF_DEFER_INSN_RESCAN);
+
++ mark_early_clobbers_alive ();
++
+ regrename_init (false);
+
+ regrename_analyze (NULL);
+
+From 23951fbf9ef78f3106624afd857e738ee56d3663 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 20 Apr 2017 09:34:00 +0200
+Subject: [PATCH 074/303] @B modified clobber for regrename with regparm
+
+---
+ gcc/config/m68k/amigaos.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index 09934f94c06d..a598406ca132 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -591,7 +591,10 @@ void amiga_emit_regparm_clobbers(void)
+ {
+ for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+ if (mycum.regs_already_used & (1 << i))
+- emit_insn(gen_rtx_CLOBBER(Pmode, gen_raw_REG(Pmode, i)));
++ {
++ rtx reg = gen_raw_REG(Pmode, i);
++ emit_insn(gen_rtx_CLOBBER(Pmode, gen_rtx_SET(reg, reg)));
++ }
+ }
+
+
+
+From 6186c919f785d5f0ed760ac3e164510098e106aa Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 20 Apr 2017 18:29:48 +0200
+Subject: [PATCH 075/303] @R half way through to own rename
+
+---
+ gcc/bbb-opts.c | 240 +++++++++++++++++++++++++++++++++++++++-------
+ gcc/config/m68k/amigaos.c | 3 +-
+ gcc/regrename.c | 26 +----
+ 3 files changed, 208 insertions(+), 61 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 2c19242512a2..7a3a716193c4 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -49,6 +49,7 @@
+ #include "cselib.h"
+ #include "langhooks.h"
+ #include <vector>
++#include <set>
+ #include <map>
+
+ static bool be_verbose;
+@@ -94,11 +95,12 @@ log (char const * fmt, ...)
+ */
+ struct insn_info
+ {
+- unsigned _use;
+- unsigned _def;
++ unsigned _use; // bit set if registers are used
++ unsigned _def; // bit set if registers are defined
++ unsigned _hard; // bit set if registers can't be renamed
+
+ insn_info () :
+- _use (0), _def (0)
++ _use (0), _def (0), _hard (0)
+ {
+ }
+
+@@ -107,6 +109,7 @@ struct insn_info
+ {
+ _use = 0;
+ _def = 0;
++ _hard = 0;
+ }
+
+ inline void
+@@ -121,11 +124,18 @@ struct insn_info
+ _def |= 1 << regno;
+ }
+
++ inline void
++ hard (int regno)
++ {
++ _hard |= 1 << regno;
++ }
++
+ inline void
+ unset (int regno)
+ {
+ _use &= ~(1 << regno);
+ _def &= ~(1 << regno);
++ _hard &= ~(1 << regno);
+ }
+
+ inline bool
+@@ -140,12 +150,19 @@ struct insn_info
+ return (_def & (1 << regno)) != 0;
+ }
+
++ inline bool
++ is_hard (int regno)
++ {
++ return (_hard & (1 << regno)) != 0;
++ }
++
+ inline insn_info
+ operator | (insn_info const & o) const
+ {
+ insn_info t;
+ t._use = _use | o._use;
+ t._def = _def | o._def;
++ t._hard = _hard | o._hard;
+ return t;
+ }
+
+@@ -154,6 +171,7 @@ struct insn_info
+ {
+ _use |= o._use;
+ _def |= o._def;
++ _hard |= o._hard;
+ return *this;
+ }
+
+@@ -162,6 +180,7 @@ struct insn_info
+ {
+ _use &= o._use & o._def;
+ _def &= o._def;
++ _hard &= o._hard & o._def;
+ return *this;
+ }
+
+@@ -177,6 +196,7 @@ struct insn_info
+ insn_info t;
+ t._use = ~_use;
+ t._def = ~_def;
++ t._hard = ~_hard;
+ return t;
+ }
+
+@@ -194,9 +214,12 @@ struct insn_info
+ scan (rtx);
+
+ unsigned
+- get_def_mask () const
++ get_free_mask () const
+ {
+- if (!_def || _def > 0x7fff)
++ if (_def & _hard)
++ return 0;
++
++ if (!_def || _def > 0x1000)
+ return 0;
+
+ unsigned mask = _def - 1;
+@@ -204,11 +227,10 @@ struct insn_info
+ if ((mask & ~_def) != mask)
+ return 0;
+
+- if (_def > 0x1000)
+- return 0;
+ if (_def > 0xff)
+ mask &= 0xff00;
+- return mask;
++
++ return mask & ~_use;
+ }
+ };
+
+@@ -271,6 +293,7 @@ do_reg_rename (rtx x, unsigned oldregno, unsigned newregno)
+ * Collect some data.
+ */
+ static std::vector<rtx_insn *> insns;
++static std::vector<bool> proepilogue;
+ static std::vector<rtx_insn *> temp;
+ static std::vector<rtx_insn *> jumps;
+ static std::map<rtx_insn *, unsigned> insn2index;
+@@ -283,6 +306,7 @@ static void
+ clear (void)
+ {
+ insns.clear ();
++ proepilogue.clear ();
+ jumps.clear ();
+ insn2index.clear ();
+ infos.clear ();
+@@ -333,11 +357,23 @@ dump_insns (char const * name, bool all)
+
+ for (int j = 0; j < 8; ++j)
+ if (ii.is_use (j))
+- fprintf (stderr, ii.is_def (j) ? "*d%d " : "d%d ", j);
++ {
++ if (ii.is_hard (j))
++ fprintf (stderr, "!");
++ if (ii.is_def (j))
++ fprintf (stderr, "*");
++ fprintf (stderr, "d%d ", j);
++ }
+
+ for (int j = 8; j < 16; ++j)
+ if (ii.is_use (j))
+- fprintf (stderr, ii.is_def (j) ? "*a%d " : "a%d ", j - 8);
++ {
++ if (ii.is_hard (j))
++ fprintf (stderr, "!");
++ if (ii.is_def (j))
++ fprintf (stderr, "*");
++ fprintf (stderr, "a%d ", j - 8);
++ }
+
+ if (ii.is_use (FIRST_PSEUDO_REGISTER))
+ fprintf (stderr, ii.is_def (FIRST_PSEUDO_REGISTER) ? "*cc " : "cc ");
+@@ -367,6 +403,7 @@ update_insns ()
+
+ df_insn_rescan_all ();
+
++ bool inproepilogue = true;
+ /* create a vector with relevant insn. */
+ for (insn = get_insns (); insn; insn = next)
+ {
+@@ -379,6 +416,18 @@ update_insns ()
+
+ insn2index.insert (std::make_pair (insn, insns.size ()));
+ insns.push_back (insn);
++ proepilogue.push_back (inproepilogue);
++
++ if (JUMP_P(insn))
++ inproepilogue = false;
++ }
++
++ if (NOTE_P(insn))
++ {
++ if (NOTE_KIND(insn) == NOTE_INSN_PROLOGUE_END)
++ inproepilogue = false;
++ else if (NOTE_KIND(insn) == NOTE_INSN_EPILOGUE_BEG)
++ inproepilogue = true;
+ }
+ }
+ }
+@@ -447,6 +496,8 @@ update_insn_infos (void)
+ for (unsigned r = REGNO(reg); r <= END_REGNO (reg); ++r)
+ use.use (r);
+ }
++ /* also mark all registers as not renamable */
++ use._hard = use._use;
+
+ rtx set = single_set (insn);
+ if (set)
+@@ -457,15 +508,11 @@ update_insn_infos (void)
+ else
+ use.scan (pattern);
+
+- /* fix missing defs - a call sets d0 and maybe also d1,a0,a1. */
+- if (ii.is_use (0))
+- def.def (0);
+- if (ii.is_use (1))
+- def.def (1);
+- if (ii.is_use (8))
+- def.def (8);
+- if (ii.is_use (9))
+- def.def (9);
++ /* mark scratch registers. */
++ def.def (0);
++ def.def (1);
++ def.def (8);
++ def.def (9);
+
+ infos[pos] = def | use | ii;
+
+@@ -501,26 +548,37 @@ update_insn_infos (void)
+ {
+ rtx x = XEXP(pattern, 0);
+ if (REG_P(x))
+- ii.use (REGNO(x));
++ {
++ ii.use (REGNO(x));
++ ii.hard (REGNO(x));
++ }
+ infos[pos] = ii;
+ continue;
+ }
+
+- if (GET_CODE (pattern) == CLOBBER ) {
++ if (GET_CODE (pattern) == CLOBBER)
++ {
+ /* mark regs as use and def */
+ insn_info ud;
+- ud.scan(pattern);
++ ud.scan (pattern);
+ ud._def |= ud._use;
++ ud._hard = ud._use; /* don't rename. */
+ infos[pos] |= ud;
+ continue;
+- }
+- if (GET_CODE (pattern) != PARALLEL && GET_CODE (pattern) != CLOBBER && be_verbose)
++ }
++ if (GET_CODE (pattern) != PARALLEL && be_verbose)
+ {
+ fprintf (stderr, "##### ");
+ debug_rtx (insn);
+ }
+- ii.scan (pattern);
+- infos[pos] = ii;
++
++ insn_info jj;
++ jj.scan (pattern);
++
++ if (proepilogue[pos])
++ jj._hard = jj._use | jj._def;
++
++ infos[pos] = ii | jj;
+ continue;
+ }
+
+@@ -549,6 +607,9 @@ update_insn_infos (void)
+ def.def (FIRST_PSEUDO_REGISTER);
+ }
+
++ if (proepilogue[pos])
++ ii._hard |= use._use | def._def;
++
+ infos[pos] = def | use | ii;
+
+ ii &= ~def;
+@@ -558,6 +619,114 @@ update_insn_infos (void)
+ }
+ }
+
++static int
++bit2regno (unsigned bit)
++{
++ if (!bit)
++ return -1;
++
++ unsigned regno = 0;
++ while (!(bit & 1))
++ {
++ ++regno;
++ bit >>= 1;
++ }
++ return regno;
++}
++
++/*
++ * Always prefer lower register numbers within the class.
++ */
++static unsigned
++bb_reg_rename (void)
++{
++// dump_insns ("rename", 1);
++ for (unsigned index = 0; index < insns.size (); ++index)
++ {
++ insn_info & ii = infos[index];
++ const unsigned def = ii._def & ~ii._hard;
++ unsigned mask = ii.get_free_mask ();
++
++ if (!mask || !def)
++ continue;
++
++ std::set<unsigned> found;
++ std::vector<unsigned> todo;
++ if (index + 1 < insns.size ())
++ todo.push_back (index + 1);
++
++ found.insert (index);
++ /* a register was defined, follow all branches. */
++ while (todo.size ())
++ {
++ unsigned pos = todo[todo.size () - 1];
++ todo.pop_back ();
++
++ if (found.find (pos) != found.end ())
++ continue;
++
++ if (LABEL_P(insns[pos]))
++ {
++ if (pos + 1 < insns.size ())
++ todo.push_back (pos + 1);
++ continue;
++ }
++
++ insn_info & jj = infos[pos];
++
++ /* not used. */
++ if (!(jj._use & def))
++ continue;
++
++ /* update free regs. */
++ mask &= ~jj._use;
++ mask &= ~jj._def;
++ if (!mask)
++ break;
++
++
++ found.insert (pos);
++
++ /* follow jump and/or next insn. */
++ rtx_insn * insn = insns[pos];
++ if (JUMP_P(insn))
++ {
++ std::map<rtx_insn *, unsigned>::iterator j = insn2index.find ((rtx_insn *) JUMP_LABEL(insn));
++ if (j != insn2index.end ())
++ todo.push_back (j->second);
++
++ rtx jmppattern = PATTERN (insn);
++
++ rtx jmpsrc = XEXP(jmppattern, 1);
++ if (GET_CODE(jmpsrc) == IF_THEN_ELSE)
++ if (pos + 1 < insns.size ())
++ todo.push_back (pos + 1);
++ }
++ else if (pos + 1 < insns.size ())
++ todo.push_back (pos + 1);
++ }
++
++ if (mask)
++ {
++ int oldregno = bit2regno (def);
++ int newregno = bit2regno (mask);
++ log ("bb_reg_rename %s -> %s (%d insns)\n", reg_names[oldregno], reg_names[newregno], found.size ());
++
++ for (std::set<unsigned>::iterator i = found.begin (); i != found.end (); ++i)
++ {
++// if (be_verbose)
++// debug_rtx (insns[*i]);
++ do_reg_rename (PATTERN (insns[*i]), oldregno, newregno);
++ }
++
++ cselib_invalidate_rtx (gen_raw_REG (SImode, oldregno));
++ cselib_invalidate_rtx (gen_raw_REG (SImode, newregno));
++ return 1;
++ }
++ }
++ return 0;
++}
++
+ /*
+ * #1 propagate a->b->a moves out of a loop.
+ *
+@@ -1841,18 +2010,19 @@ namespace
+ done = 0, update_insns (), update_insn_infos ();
+
+ if (do_elim_dead_assign && elim_dead_assign ())
+- done = 0, update_insns ();
++ done = 0, update_insns (), update_insn_infos ();
+
+ if (do_bb_reg_rename && ::global_pass_regrename)
+ {
+- class opt_pass * rr = ::global_pass_regrename->clone ();
+- rr->execute (0);
+-
+- // update_insns ();
+- // update_insn_infos ();
+- // bb_reg_rename ();
+-
+- update_insns ();
++// class opt_pass * rr = ::global_pass_regrename->clone ();
++// rr->execute (0);
++
++ while (bb_reg_rename ())
++ {
++ update_insns ();
++ update_insn_infos ();
++ done = 0;
++ }
+ }
+
+ if (done)
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index a598406ca132..dd5707612119 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -589,11 +589,12 @@ amigaos_function_arg (cumulative_args_t cum_v, machine_mode mode,
+
+ void amiga_emit_regparm_clobbers(void)
+ {
++ rtx sp = gen_raw_REG(Pmode, 15);
+ for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+ if (mycum.regs_already_used & (1 << i))
+ {
+ rtx reg = gen_raw_REG(Pmode, i);
+- emit_insn(gen_rtx_CLOBBER(Pmode, gen_rtx_SET(reg, reg)));
++ emit_insn(gen_rtx_CLOBBER(Pmode, gen_rtx_SET(reg, gen_rtx_MEM(Pmode, reg))));
+ }
+ }
+
+diff --git a/gcc/regrename.c b/gcc/regrename.c
+index eceb7286e31e..fad839f8f926 100755
+--- gcc/regrename.c
++++ gcc/regrename.c
+@@ -1892,28 +1892,6 @@ regrename_finish (void)
+ obstack_free (&rename_obstack, NULL);
+ }
+
+-void
+-mark_early_clobbers_alive (void)
+-{
+- rtx_insn * insn;
+- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+- {
+- rtx pattern;
+- if (NOTE_P(insn) && NOTE_KIND(insn) == NOTE_INSN_PROLOGUE_END)
+- break;
+-
+- pattern = PATTERN (insn);
+- if (pattern && GET_CODE(pattern) == CLOBBER)
+- {
+- rtx *loc;
+-
+- loc = &REG_NOTES(insn);
+- while (*loc)
+- *loc = XEXP(*loc, 1);
+- }
+- }
+-}
+-
+ /* Perform register renaming on the current function. */
+
+ static unsigned int
+@@ -1924,8 +1902,6 @@ regrename_optimize (void)
+ df_analyze ();
+ df_set_flags (DF_DEFER_INSN_RESCAN);
+
+- mark_early_clobbers_alive ();
+-
+ regrename_init (false);
+
+ regrename_analyze (NULL);
+@@ -1965,7 +1941,7 @@ class pass_regrename : public rtl_opt_pass
+ /* opt_pass methods: */
+ virtual bool gate (function *)
+ {
+- return (optimize > 0 && (flag_rename_registers));
++ return (optimize > 0 && (flag_rename_registers) && !TARGET_AMIGA);
+ }
+
+ virtual unsigned int execute (function *) { return regrename_optimize (); }
+
+From bab57d7745f2399e3bf6c23f9803ae188bf576ea Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sat, 22 Apr 2017 16:23:35 +0200
+Subject: [PATCH 076/303] @R own rename registers seems to work.
+
+---
+ gcc/bbb-opts.c | 350 ++++++++++++++++++++++++++++++++++++--------------------
+ gcc/cfgbuild.c | 1 +
+ gcc/regrename.c | 3 -
+ 3 files changed, 225 insertions(+), 129 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 7a3a716193c4..1f70ffecc2d4 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -175,13 +175,20 @@ struct insn_info
+ return *this;
+ }
+
+- inline insn_info &
+- operator &= (insn_info const & o)
++ /*
++ * update for previous insn.
++ * - remove regs which are defined here
++ * - add regs which are used here
++ * - reset _def
++ * - restrain _hard to used
++ */
++ inline void
++ updateWith (insn_info const & o)
+ {
+- _use &= o._use & o._def;
+- _def &= o._def;
+- _hard &= o._hard & o._def;
+- return *this;
++ _use &= ~o._def;
++ _use |= o._use;
++ _def = 0;
++ _hard &= ~_use;
+ }
+
+ inline bool
+@@ -252,6 +259,24 @@ insn_info::scan (rtx x)
+ }
+
+ RTX_CODE code = GET_CODE(x);
++
++ /* handle SET and record use and def. */
++ if (code == SET)
++ {
++ unsigned u = _use;
++ scan (SET_DEST(x));
++ if (REG_P(SET_DEST(x)))
++ {
++ _def = _use;
++ _use = u;
++ }
++ scan (SET_SRC(x));
++ int code = GET_CODE(SET_SRC(x));
++ if (code == ASM_OPERANDS)
++ _hard |= _def | _use;
++ return;
++ }
++
+ const char *fmt = GET_RTX_FORMAT(code);
+ for (int i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ {
+@@ -263,14 +288,63 @@ insn_info::scan (rtx x)
+ }
+ }
+
++static rtx
++copy_reg(rtx reg, int newregno)
++{
++ if (newregno < 0)
++ newregno = REGNO(reg);
++ rtx x = gen_raw_REG(GET_MODE(reg), newregno);
++ x->jump = reg->jump;
++ x->call = reg->call;
++ x->unchanging = reg->unchanging;
++ x->volatil = reg->volatil;
++ x->in_struct = reg->in_struct;
++ x->used = reg->used;
++ x->frame_related = reg->frame_related;
++ x->return_val = reg->return_val;
++
++ x->u.reg.attrs = reg->u.reg.attrs;
++ return x;
++}
++
++static void
++validate_rename (std::vector<std::pair<rtx *, rtx>> & loc, rtx x, unsigned oldregno, unsigned newregno)
++{
++ RTX_CODE code = GET_CODE(x);
++
++ const char *fmt = GET_RTX_FORMAT(code);
++ for (int i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
++ {
++ if (fmt[i] == 'e')
++ {
++ rtx y = XEXP(x, i);
++ if (REG_P(y))
++ {
++ if (REGNO(y) == oldregno)
++ {
++ rtx z = copy_reg(y, newregno);
++ loc.push_back (std::make_pair (&XEXP(x, i), y));
++ XEXP(x, i) = z;
++ }
++ }
++ else
++ validate_rename (loc, y, oldregno, newregno);
++ }
++ else if (fmt[i] == 'E')
++ for (int j = XVECLEN (x, i) - 1; j >= 0; j--)
++ validate_rename (loc, XVECEXP(x, i, j), oldregno, newregno);
++ }
++}
++
+ /* perform reg renaming. */
+ static void
+-do_reg_rename (rtx x, unsigned oldregno, unsigned newregno)
++do_reg_rename (rtx * loc, unsigned oldregno, unsigned newregno)
+ {
++ rtx x = *loc;
+ if (REG_P(x))
+ {
+ if (REGNO(x) == oldregno)
+- df_ref_change_reg_with_loc (x, newregno);
++ *loc = copy_reg(x, newregno);
+ return;
+ }
+
+@@ -282,10 +356,10 @@ do_reg_rename (rtx x, unsigned oldregno, unsigned newregno)
+ for (int i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'e')
+- do_reg_rename (XEXP(x, i), oldregno, newregno);
++ do_reg_rename (&XEXP(x, i), oldregno, newregno);
+ else if (fmt[i] == 'E')
+ for (int j = XVECLEN (x, i) - 1; j >= 0; j--)
+- do_reg_rename (XVECEXP(x, i, j), oldregno, newregno);
++ do_reg_rename (&XVECEXP(x, i, j), oldregno, newregno);
+ }
+ }
+
+@@ -356,7 +430,7 @@ dump_insns (char const * name, bool all)
+ insn_info & ii = infos[i];
+
+ for (int j = 0; j < 8; ++j)
+- if (ii.is_use (j))
++ if (ii.is_use (j) || ii.is_def (j))
+ {
+ if (ii.is_hard (j))
+ fprintf (stderr, "!");
+@@ -366,7 +440,7 @@ dump_insns (char const * name, bool all)
+ }
+
+ for (int j = 8; j < 16; ++j)
+- if (ii.is_use (j))
++ if (ii.is_use (j) || ii.is_def (j))
+ {
+ if (ii.is_hard (j))
+ fprintf (stderr, "!");
+@@ -436,15 +510,15 @@ static void
+ update_insn_infos (void)
+ {
+ /* prepare insn_info */
+- insn_info ii;
++ insn_info ii0;
+ for (unsigned i = 0; i < insns.size (); ++i)
+ {
+- infos.push_back (ii);
++ infos.push_back (ii0);
+ }
+
+ /* own analyze reg life */
+ std::vector<std::pair<unsigned, insn_info>> todo;
+- todo.push_back (std::make_pair (insns.size () - 1, ii));
++ todo.push_back (std::make_pair (insns.size () - 1, ii0));
+
+ int pass = 0;
+ while (!todo.empty ())
+@@ -484,7 +558,6 @@ update_insn_infos (void)
+
+ if (CALL_P(insn))
+ {
+- insn_info def;
+ insn_info use;
+
+ /* add mregparm registers. */
+@@ -499,25 +572,16 @@ update_insn_infos (void)
+ /* also mark all registers as not renamable */
+ use._hard = use._use;
+
+- rtx set = single_set (insn);
+- if (set)
+- {
+- use.scan (SET_SRC(set));
+- def.scan (SET_DEST(set));
+- }
+- else
+- use.scan (pattern);
++ use.scan (pattern);
+
+ /* mark scratch registers. */
+- def.def (0);
+- def.def (1);
+- def.def (8);
+- def.def (9);
+-
+- infos[pos] = def | use | ii;
++ use.def (0);
++ use.def (1);
++ use.def (8);
++ use.def (9);
+
+- ii &= ~def;
+- ii |= use;
++ infos[pos] = use | ii;
++ ii.updateWith (use);
+
+ continue;
+ }
+@@ -525,95 +589,60 @@ update_insn_infos (void)
+ if (JUMP_P(insn))
+ {
+ if (ANY_RETURN_P(pattern))
+- {
+- ii.reset ();
+-// ii.use (0);
+- }
+- else
+- {
+- ii |= infos[pos];
++ ii.reset ();
+
+- // check for reg use
+- ii.scan (PATTERN (insn));
++ insn_info use;
++ use.scan (pattern);
++ infos[pos] = use | ii;
++ ii.updateWith (use);
+
+- }
+- infos[pos] = ii;
+ continue;
+ }
+
+- rtx set = single_set (insn);
+- if (set == 0)
++ if (GET_CODE (pattern) == USE)
+ {
+- if (GET_CODE (pattern) == USE)
+- {
+- rtx x = XEXP(pattern, 0);
+- if (REG_P(x))
+- {
+- ii.use (REGNO(x));
+- ii.hard (REGNO(x));
+- }
+- infos[pos] = ii;
+- continue;
+- }
+-
+- if (GET_CODE (pattern) == CLOBBER)
+- {
+- /* mark regs as use and def */
+- insn_info ud;
+- ud.scan (pattern);
+- ud._def |= ud._use;
+- ud._hard = ud._use; /* don't rename. */
+- infos[pos] |= ud;
+- continue;
+- }
+- if (GET_CODE (pattern) != PARALLEL && be_verbose)
++ rtx x = XEXP(pattern, 0);
++ if (REG_P(x))
+ {
+- fprintf (stderr, "##### ");
+- debug_rtx (insn);
++ ii.use (REGNO(x));
++ ii.hard (REGNO(x));
+ }
++ infos[pos] = ii;
++ continue;
++ }
+
+- insn_info jj;
+- jj.scan (pattern);
+-
+- if (proepilogue[pos])
+- jj._hard = jj._use | jj._def;
+-
+- infos[pos] = ii | jj;
++ if (GET_CODE (pattern) == CLOBBER)
++ {
++ /* mark regs as use and def */
++ insn_info use;
++ use.scan (pattern);
++ use._hard = use._use = use._def = use._use | use._def;
++ infos[pos] = use | ii;
++ ii.updateWith (use);
+ continue;
+ }
+
+- rtx src = SET_SRC(set);
+- rtx dst = SET_DEST(set);
+- // scan insn for regs
+- // a def stop propagation
+- // a use starts propagation
+- // also add use to current ii
+ insn_info use;
+- insn_info def;
+-
+- use.scan (src);
+- if (REG_P(dst))
+- def.def (REGNO(dst));
+- else if (dst == cc0_rtx)
+- def.def (FIRST_PSEUDO_REGISTER);
+- else
+- use.scan (dst);
++ use.scan (pattern);
++ if (single_set (insn) == 0)
++ use._hard = use._use | use._def;
+
+- if (dst != cc0_rtx)
++ /* if not cc0 defined check for mod. */
++ if (!use.is_def (FIRST_PSEUDO_REGISTER))
+ {
+ CC_STATUS_INIT;
+ NOTICE_UPDATE_CC(PATTERN (insn), insn);
+ if (cc_status.value1 || cc_status.value2)
+- def.def (FIRST_PSEUDO_REGISTER);
++ use.def (FIRST_PSEUDO_REGISTER);
+ }
+
++ /* mark not renameable in prologue/epilogue. */
+ if (proepilogue[pos])
+- ii._hard |= use._use | def._def;
+-
+- infos[pos] = def | use | ii;
++ use._hard = use._use | use._def;
+
+- ii &= ~def;
+- ii |= use;
++ ii._use &= ~use._def;
++ infos[pos] = use | ii;
++ ii.updateWith (use);
+ }
+ ++pass;
+ }
+@@ -644,10 +673,15 @@ bb_reg_rename (void)
+ for (unsigned index = 0; index < insns.size (); ++index)
+ {
+ insn_info & ii = infos[index];
+- const unsigned def = ii._def & ~ii._hard;
+- unsigned mask = ii.get_free_mask ();
+
+- if (!mask || !def)
++ /* do not rename if register is hard or used in same statement. */
++ const unsigned toRename = ii._def & ~ii._hard & ~ii._use;
++ if (!toRename)
++ continue;
++
++ /* get the mask for free registers. */
++ unsigned mask = ii.get_free_mask ();
++ if (!mask)
+ continue;
+
+ std::set<unsigned> found;
+@@ -675,16 +709,22 @@ bb_reg_rename (void)
+ insn_info & jj = infos[pos];
+
+ /* not used. */
+- if (!(jj._use & def))
++ if (!(jj._use & toRename))
+ continue;
+
++ /* marked as hard reg -> invalid rename */
++ if (jj._hard & toRename)
++ {
++ mask = 0;
++ break;
++ }
++
+ /* update free regs. */
+ mask &= ~jj._use;
+ mask &= ~jj._def;
+ if (!mask)
+ break;
+
+-
+ found.insert (pos);
+
+ /* follow jump and/or next insn. */
+@@ -696,6 +736,11 @@ bb_reg_rename (void)
+ todo.push_back (j->second);
+
+ rtx jmppattern = PATTERN (insn);
++ if (GET_CODE(jmppattern) == PARALLEL)
++ {
++ return 0; /* can't handle yet. */
++// jmppattern = XVECEXP(jmppattern, 0, 0);
++ }
+
+ rtx jmpsrc = XEXP(jmppattern, 1);
+ if (GET_CODE(jmpsrc) == IF_THEN_ELSE)
+@@ -708,19 +753,69 @@ bb_reg_rename (void)
+
+ if (mask)
+ {
+- int oldregno = bit2regno (def);
++ int oldregno = bit2regno (toRename);
+ int newregno = bit2regno (mask);
+- log ("bb_reg_rename %s -> %s (%d insns)\n", reg_names[oldregno], reg_names[newregno], found.size ());
+
+- for (std::set<unsigned>::iterator i = found.begin (); i != found.end (); ++i)
++ /* check the renamed insns. */
++ std::vector<std::pair<rtx *, rtx>> locs;
++ bool ok = true;
++ std::vector<unsigned> patch;
++ for (std::set<unsigned>::iterator i = found.begin (); ok && i != found.end (); ++i)
+ {
+-// if (be_verbose)
+-// debug_rtx (insns[*i]);
+- do_reg_rename (PATTERN (insns[*i]), oldregno, newregno);
++ rtx_insn * insn = insns[*i];
++ validate_rename (locs, PATTERN (insn), oldregno, newregno);
++
++ if (!locs.empty ())
++ {
++ int num_clobbers_to_add = 0;
++ int insn_code_number = recog (PATTERN (insn), insn, &num_clobbers_to_add);
++ if (insn_code_number < 0 || !check_asm_operands (PATTERN (insn)))
++ {
++ fprintf (stderr, "renaming %d -> %d failed: ", oldregno, newregno);
++ debug_rtx (insn);
++ for (std::vector<std::pair<rtx *, rtx>>::iterator j = locs.begin (); j != locs.end (); ++j)
++ {
++ debug_rtx (*j->first);
++ debug_rtx (j->second);
++ }
++ ok = false;
++ }
++
++ for (std::vector<std::pair<rtx *, rtx>>::iterator j = locs.begin (); j != locs.end (); ++j)
++ *j->first = j->second;
++
++ if (!ok)
++ {
++ fprintf (stderr, "restored: ", oldregno, newregno);
++ debug_rtx (insn);
++ for (std::vector<std::pair<rtx *, rtx>>::iterator j = locs.begin (); j != locs.end (); ++j)
++ {
++ debug_rtx (*j->first);
++ debug_rtx (j->second);
++ }
++ }
++ locs.clear ();
++
++ patch.push_back(*i);
++ }
+ }
+
+- cselib_invalidate_rtx (gen_raw_REG (SImode, oldregno));
+- cselib_invalidate_rtx (gen_raw_REG (SImode, newregno));
++ if (!ok)
++ continue;
++
++ log ("bb_reg_rename %s -> %s (%d insns)\n", reg_names[oldregno], reg_names[newregno], patch.size ());
++
++ for (std::vector<unsigned>::iterator i = patch.begin (); i != patch.end (); ++i)
++ {
++ rtx_insn * insn = insns[*i];
++ rtx pattern = PATTERN (insn);
++ SET_INSN_DELETED(insn);
++ do_reg_rename (&pattern, oldregno, newregno);
++ emit_insn_after(pattern, insn);
++ }
++
++// cselib_invalidate_rtx (gen_raw_REG (SImode, oldregno));
++// cselib_invalidate_rtx (gen_raw_REG (SImode, newregno));
+ return 1;
+ }
+ }
+@@ -1209,7 +1304,7 @@ commute_add_move (void)
+
+ SET_INSN_DELETED(insn);
+
+- insn = emit_insn_before (newinsn, next);
++ insn = emit_insn_before (PATTERN (newinsn), next);
+
+ add_reg_note (next, REG_INC, reg1dst);
+
+@@ -1295,28 +1390,33 @@ const_cmp_to_sub (void)
+ continue;
+
+ int intval = -INTVAL(srcp);
+- if (intval < -8 || intval > 7)
++ if (intval < -8 || intval > 7 || intval == 0)
+ continue;
+
+ enum machine_mode mode = GET_MODE(dstp);
++ if (GET_MODE_SIZE(mode) > 4)
++ continue;
++
++ // printf("mode size: %d\n", GET_MODE_SIZE(mode));
++
+ rtx reg = dstp == left ? right : left;
+- rtx plus = gen_rtx_PLUS(mode, reg, gen_rtx_CONST_INT (mode, intval));
++ rtx plus = gen_rtx_PLUS(mode, copy_reg(reg, -1), gen_rtx_CONST_INT (mode, intval));
+
+- rtx_insn * neuprev = make_insn_raw (gen_rtx_SET(reg, plus));
++ rtx_insn * neuprev = make_insn_raw (gen_rtx_SET(copy_reg(reg, -1), plus));
+
+ int num_clobbers_to_add = 0;
+ int insn_code_number = recog (PATTERN (neuprev), neuprev, &num_clobbers_to_add);
+- if (insn_code_number >= 0 && !check_asm_operands (PATTERN (neuprev)))
++ if (insn_code_number < 0 || !check_asm_operands (PATTERN (neuprev)))
+ continue;
+
+ // also convert current statement to cmp #0, reg
+ SET_INSN_DELETED(insn);
+- rtx neu = gen_rtx_SET(cc0_rtx, gen_rtx_COMPARE(mode, reg, gen_rtx_CONST_INT(mode, 0)));
++ rtx neu = gen_rtx_SET(cc0_rtx, gen_rtx_COMPARE(mode, copy_reg(reg, -1), gen_rtx_CONST_INT(mode, 0)));
+ insn = emit_insn_after (neu, prev);
+ add_reg_note (insn, REG_DEAD, reg);
+
+ SET_INSN_DELETED(prev);
+- prev = emit_insn_before (neuprev, insn);
++ prev = emit_insn_before (PATTERN (neuprev), insn);
+
+ log ("const_cmp_to_sub replaced reg-reg compare with sub\n");
+
+@@ -1537,7 +1637,7 @@ shrink_stack_frame (void)
+ return 0;
+
+ bool usea5 = false;
+- unsigned paramstart = 4;
++ int paramstart = 4;
+ int a5offset = 0;
+
+ /*
+@@ -1696,6 +1796,9 @@ shrink_stack_frame (void)
+ insn_info ii;
+ for (unsigned i = 0; i < infos.size (); ++i)
+ {
++ if (proepilogue[i])
++ continue;
++
+ insn_info & jj = infos[i];
+ ii |= jj;
+ }
+@@ -1914,8 +2017,6 @@ shrink_stack_frame (void)
+ return 0;
+ }
+
+-extern class opt_pass * global_pass_regrename;
+-
+ namespace
+ {
+
+@@ -2012,11 +2113,8 @@ namespace
+ if (do_elim_dead_assign && elim_dead_assign ())
+ done = 0, update_insns (), update_insn_infos ();
+
+- if (do_bb_reg_rename && ::global_pass_regrename)
++ if (do_bb_reg_rename)
+ {
+-// class opt_pass * rr = ::global_pass_regrename->clone ();
+-// rr->execute (0);
+-
+ while (bb_reg_rename ())
+ {
+ update_insns ();
+diff --git a/gcc/cfgbuild.c b/gcc/cfgbuild.c
+index c1ec46ad8d7f..1f488dc54544 100644
+--- gcc/cfgbuild.c
++++ gcc/cfgbuild.c
+@@ -55,6 +55,7 @@ inside_basic_block_p (const rtx_insn *insn)
+ case DEBUG_INSN:
+ return true;
+
++ case DEBUG_IMPLICIT_PTR:
+ case JUMP_TABLE_DATA:
+ case BARRIER:
+ case NOTE:
+diff --git a/gcc/regrename.c b/gcc/regrename.c
+index fad839f8f926..3d1e87af39fc 100755
+--- gcc/regrename.c
++++ gcc/regrename.c
+@@ -1913,8 +1913,6 @@ regrename_optimize (void)
+ return 0;
+ }
+
+-class opt_pass * global_pass_regrename;
+-
+ namespace {
+
+ const pass_data pass_data_regrename =
+@@ -1935,7 +1933,6 @@ class pass_regrename : public rtl_opt_pass
+ pass_regrename (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_regrename, ctxt)
+ {
+- ::global_pass_regrename = this;
+ }
+
+ /* opt_pass methods: */
+
+From 7b2b67ccbe0e6ea8a226071a001cdeac5a493a1d Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sat, 22 Apr 2017 16:31:08 +0200
+Subject: [PATCH 077/303] @R restored original regrename.c, since no longer
+ used with TARGET_AMIGA. Only left the fix for df
+
+---
+ gcc/regrename.c | 34 +++++++++++++++++-----------------
+ 1 file changed, 17 insertions(+), 17 deletions(-)
+
+diff --git a/gcc/regrename.c b/gcc/regrename.c
+index 3d1e87af39fc..1ed6557ee713 100755
+--- gcc/regrename.c
++++ gcc/regrename.c
+@@ -356,9 +356,8 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class,
+ {
+ bool has_preferred_class;
+ enum reg_class preferred_class;
++ int pass;
+ int best_new_reg = old_reg;
+- int new_reg;
+- int hit = 0;
+
+ /* Further narrow the set of registers we can use for renaming.
+ If the chain needs a call-saved register, mark the call-used
+@@ -371,14 +370,14 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class,
+
+ /* Compute preferred rename class of super union of all the classes
+ in the chain. */
+- preferred_class = (enum reg_class) targetm.preferred_rename_class2 (
+- super_class, old_reg);
++ preferred_class
++ = (enum reg_class) targetm.preferred_rename_class (super_class);
+
+ /* Pick and check the register from the tied chain iff the tied chain
+ is not renamed. */
+ if (this_head->tied_chain && !this_head->tied_chain->renamed
+- && check_new_reg_p (old_reg, this_head->tied_chain->regno, this_head,
+- *unavailable))
++ && check_new_reg_p (old_reg, this_head->tied_chain->regno,
++ this_head, *unavailable))
+ return this_head->tied_chain->regno;
+
+ /* If PREFERRED_CLASS is not NO_REGS, we iterate in the first pass
+@@ -388,10 +387,14 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class,
+ If PREFERRED_CLASS is NO_REGS, we iterate over all registers in
+ ascending order without any preference. */
+ has_preferred_class = (preferred_class != NO_REGS);
++ for (pass = (has_preferred_class ? 0 : 1); pass < 2; pass++)
++ {
++ int new_reg;
+ for (new_reg = 0; new_reg < FIRST_PSEUDO_REGISTER; new_reg++)
+ {
+ if (has_preferred_class
+- && !TEST_HARD_REG_BIT(reg_class_contents[preferred_class],
++ && (pass == 0)
++ != TEST_HARD_REG_BIT (reg_class_contents[preferred_class],
+ new_reg))
+ continue;
+
+@@ -405,11 +408,14 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class,
+ don't belong to PREFERRED_CLASS to registers that do, even
+ though the latters were used not very long ago.
+ Also use a register if no best_new_reg was found till now */
+- if (new_reg < old_reg || !hit)
+- {
+- hit = 1;
++ if (((pass == 0 || !has_preferred_class)
++ && !TEST_HARD_REG_BIT (reg_class_contents[preferred_class],
++ best_new_reg))
++ || tick[best_new_reg] > tick[new_reg])
+ best_new_reg = new_reg;
+ }
++ if (pass == 0 && best_new_reg != old_reg)
++ break;
+ }
+ return best_new_reg;
+ }
+@@ -1932,8 +1938,7 @@ class pass_regrename : public rtl_opt_pass
+ public:
+ pass_regrename (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_regrename, ctxt)
+- {
+- }
++ {}
+
+ /* opt_pass methods: */
+ virtual bool gate (function *)
+@@ -1943,11 +1948,6 @@ class pass_regrename : public rtl_opt_pass
+
+ virtual unsigned int execute (function *) { return regrename_optimize (); }
+
+- opt_pass * clone ()
+- {
+- return new pass_regrename(m_ctxt);
+- }
+-
+ }; // class pass_regrename
+
+ } // anon namespace
+
+From 8425bbc011d5d94d7e2270c00b904da4170fc644 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sat, 22 Apr 2017 19:54:50 +0200
+Subject: [PATCH 078/303] @B fix hard reg tracking in parallel insns, @I some
+ cleanup
+
+---
+ gcc/bbb-opts.c | 144 ++++++++++++++++++++++++---------------------------------
+ 1 file changed, 61 insertions(+), 83 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 1f70ffecc2d4..e7de83e59c07 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -26,9 +26,30 @@
+ * #1 propagate_moves
+ * check if a->b->a can be moved out of a loop.
+ *
+- * #2 strcpy_opt
++ * #2 strcpy
+ * check if a temp reg can be eliminated.
+ *
++ * #3 const_comp_sub
++ * convert a compare with int constant into sub statement.
++ *
++ * #4 merge_add
++ * merge adds
++ *
++ * #5 elim_dead_assign
++ * eliminate some dead assignments.
++ *
++ * #6 shrink stack frame
++ * remove push/pop for unused variables
++ *
++ * #7 rename register
++ * rename registers without breaking register parameters, inline asm etc.
++ *
++ * Lessons learned:
++ *
++ * - do not trust existing code, better delete insns and inster a new one.
++ * - do not modify insns, create new insns from pattern
++ * - do not reuse registers, create new reg rtx instances
++ *
+ */
+
+ #include "config.h"
+@@ -55,10 +76,12 @@
+ static bool be_verbose;
+
+ extern struct lang_hooks lang_hooks;
++
++/* Lookup of the current function name. */
+ extern tree current_function_decl;
+ static tree last_function_decl;
+ static char const *
+-getCurrentFunctionName ()
++get_current_function_name ()
+ {
+ static char fxname[512];
+ if (current_function_decl == NULL)
+@@ -68,6 +91,7 @@ getCurrentFunctionName ()
+ return fxname;
+ }
+
++/* a simple log to stdout. */
+ static int
+ log (char const * fmt, ...)
+ {
+@@ -79,7 +103,7 @@ log (char const * fmt, ...)
+ if (last_function_decl != current_function_decl)
+ {
+ last_function_decl = current_function_decl;
+- printf (":bbb: in '%s'\n", getCurrentFunctionName ());
++ printf (":bbb: in '%s'\n", get_current_function_name ());
+ }
+ printf (":bbb: ");
+ int retval = vprintf (fmt, args);
+@@ -88,7 +112,7 @@ log (char const * fmt, ...)
+ return retval;
+ }
+
+-/* Enough for m68k.
++/* Information for each insn to detect alive registers. Enough for m68k.
+ * Why a class? Maybe extend it for general usage.
+ *
+ * Track use & def separate to determine starting points.
+@@ -220,6 +244,7 @@ struct insn_info
+ void
+ scan (rtx);
+
++ /* return bits for alternate free registers. */
+ unsigned
+ get_free_mask () const
+ {
+@@ -267,7 +292,7 @@ insn_info::scan (rtx x)
+ scan (SET_DEST(x));
+ if (REG_P(SET_DEST(x)))
+ {
+- _def = _use;
++ _def |= _use;
+ _use = u;
+ }
+ scan (SET_SRC(x));
+@@ -288,12 +313,13 @@ insn_info::scan (rtx x)
+ }
+ }
+
++/* create a copy for a reg. Optional specify a new register number. */
+ static rtx
+-copy_reg(rtx reg, int newregno)
++copy_reg (rtx reg, int newregno)
+ {
+ if (newregno < 0)
+ newregno = REGNO(reg);
+- rtx x = gen_raw_REG(GET_MODE(reg), newregno);
++ rtx x = gen_raw_REG (GET_MODE(reg), newregno);
+ x->jump = reg->jump;
+ x->call = reg->call;
+ x->unchanging = reg->unchanging;
+@@ -307,8 +333,9 @@ copy_reg(rtx reg, int newregno)
+ return x;
+ }
+
++/* Rename the register plus track all locs to undo these changes. */
+ static void
+-validate_rename (std::vector<std::pair<rtx *, rtx>> & loc, rtx x, unsigned oldregno, unsigned newregno)
++temp_reg_rename (std::vector<std::pair<rtx *, rtx>> & loc, rtx x, unsigned oldregno, unsigned newregno)
+ {
+ RTX_CODE code = GET_CODE(x);
+
+@@ -322,44 +349,17 @@ validate_rename (std::vector<std::pair<rtx *, rtx>> & loc, rtx x, unsigned oldre
+ {
+ if (REGNO(y) == oldregno)
+ {
+- rtx z = copy_reg(y, newregno);
++ rtx z = copy_reg (y, newregno);
+ loc.push_back (std::make_pair (&XEXP(x, i), y));
+ XEXP(x, i) = z;
+ }
+ }
+ else
+- validate_rename (loc, y, oldregno, newregno);
++ temp_reg_rename (loc, y, oldregno, newregno);
+ }
+ else if (fmt[i] == 'E')
+ for (int j = XVECLEN (x, i) - 1; j >= 0; j--)
+- validate_rename (loc, XVECEXP(x, i, j), oldregno, newregno);
+- }
+-}
+-
+-/* perform reg renaming. */
+-static void
+-do_reg_rename (rtx * loc, unsigned oldregno, unsigned newregno)
+-{
+- rtx x = *loc;
+- if (REG_P(x))
+- {
+- if (REGNO(x) == oldregno)
+- *loc = copy_reg(x, newregno);
+- return;
+- }
+-
+- if (x == cc0_rtx)
+- return;
+-
+- RTX_CODE code = GET_CODE(x);
+- const char *fmt = GET_RTX_FORMAT(code);
+- for (int i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+- {
+- if (fmt[i] == 'e')
+- do_reg_rename (&XEXP(x, i), oldregno, newregno);
+- else if (fmt[i] == 'E')
+- for (int j = XVECLEN (x, i) - 1; j >= 0; j--)
+- do_reg_rename (&XVECEXP(x, i, j), oldregno, newregno);
++ temp_reg_rename (loc, XVECEXP(x, i, j), oldregno, newregno);
+ }
+ }
+
+@@ -758,64 +758,42 @@ bb_reg_rename (void)
+
+ /* check the renamed insns. */
+ std::vector<std::pair<rtx *, rtx>> locs;
++ std::vector<std::pair<rtx *, rtx>> patch;
+ bool ok = true;
+- std::vector<unsigned> patch;
++
+ for (std::set<unsigned>::iterator i = found.begin (); ok && i != found.end (); ++i)
+ {
+ rtx_insn * insn = insns[*i];
+- validate_rename (locs, PATTERN (insn), oldregno, newregno);
+
++ /* temp rename. */
++ temp_reg_rename (locs, PATTERN (insn), oldregno, newregno);
+ if (!locs.empty ())
+ {
+ int num_clobbers_to_add = 0;
+ int insn_code_number = recog (PATTERN (insn), insn, &num_clobbers_to_add);
+ if (insn_code_number < 0 || !check_asm_operands (PATTERN (insn)))
+- {
+- fprintf (stderr, "renaming %d -> %d failed: ", oldregno, newregno);
+- debug_rtx (insn);
+- for (std::vector<std::pair<rtx *, rtx>>::iterator j = locs.begin (); j != locs.end (); ++j)
+- {
+- debug_rtx (*j->first);
+- debug_rtx (j->second);
+- }
+- ok = false;
+- }
++ ok = false;
+
++ /* undo temp change but keep loc and new register. */
+ for (std::vector<std::pair<rtx *, rtx>>::iterator j = locs.begin (); j != locs.end (); ++j)
+- *j->first = j->second;
+-
+- if (!ok)
+ {
+- fprintf (stderr, "restored: ", oldregno, newregno);
+- debug_rtx (insn);
+- for (std::vector<std::pair<rtx *, rtx>>::iterator j = locs.begin (); j != locs.end (); ++j)
+- {
+- debug_rtx (*j->first);
+- debug_rtx (j->second);
+- }
++ patch.push_back (std::make_pair (j->first, *j->first));
++ *j->first = j->second;
+ }
+- locs.clear ();
+
+- patch.push_back(*i);
++ locs.clear ();
+ }
+ }
+
+ if (!ok)
+ continue;
+
+- log ("bb_reg_rename %s -> %s (%d insns)\n", reg_names[oldregno], reg_names[newregno], patch.size ());
++ log ("bb_reg_rename %s -> %s (%d locs)\n", reg_names[oldregno], reg_names[newregno], patch.size ());
+
+- for (std::vector<unsigned>::iterator i = patch.begin (); i != patch.end (); ++i)
+- {
+- rtx_insn * insn = insns[*i];
+- rtx pattern = PATTERN (insn);
+- SET_INSN_DELETED(insn);
+- do_reg_rename (&pattern, oldregno, newregno);
+- emit_insn_after(pattern, insn);
+- }
++ /* apply all changes. */
++ for (std::vector<std::pair<rtx *, rtx>>::iterator j = patch.begin (); j != patch.end (); ++j)
++ *j->first = j->second;
+
+-// cselib_invalidate_rtx (gen_raw_REG (SImode, oldregno));
+-// cselib_invalidate_rtx (gen_raw_REG (SImode, newregno));
+ return 1;
+ }
+ }
+@@ -879,7 +857,7 @@ bb_reg_rename (void)
+ * The label must only be reachable by the exit jump.
+ */
+ static unsigned
+-propagate_moves ()
++opt_propagate_moves ()
+ {
+ unsigned change_count = 0;
+ rtx_insn * current_label = 0;
+@@ -1341,7 +1319,7 @@ commute_add_move (void)
+ *
+ */
+ static unsigned
+-const_cmp_to_sub (void)
++opt_const_cmp_to_sub (void)
+ {
+ unsigned change_count = 0;
+ #if HAVE_cc0
+@@ -1400,9 +1378,9 @@ const_cmp_to_sub (void)
+ // printf("mode size: %d\n", GET_MODE_SIZE(mode));
+
+ rtx reg = dstp == left ? right : left;
+- rtx plus = gen_rtx_PLUS(mode, copy_reg(reg, -1), gen_rtx_CONST_INT (mode, intval));
++ rtx plus = gen_rtx_PLUS(mode, copy_reg (reg, -1), gen_rtx_CONST_INT (mode, intval));
+
+- rtx_insn * neuprev = make_insn_raw (gen_rtx_SET(copy_reg(reg, -1), plus));
++ rtx_insn * neuprev = make_insn_raw (gen_rtx_SET(copy_reg (reg, -1), plus));
+
+ int num_clobbers_to_add = 0;
+ int insn_code_number = recog (PATTERN (neuprev), neuprev, &num_clobbers_to_add);
+@@ -1532,7 +1510,7 @@ elim_dead_assign (void)
+ add.l d1,a1
+ */
+ static unsigned
+-merge_add (void)
++opt_merge_add (void)
+ {
+ unsigned change_count = 0;
+ for (unsigned index = 0; index + 2 < insns.size (); ++index)
+@@ -1623,7 +1601,7 @@ clear_temp ()
+ * newstartvalue = startvalue - omitted pushes
+ */
+ static unsigned
+-shrink_stack_frame (void)
++opt_shrink_stack_frame (void)
+ {
+ /* nothing to do. */
+ if (!insns.size ())
+@@ -2100,14 +2078,14 @@ namespace
+ if (do_commute_add_move && commute_add_move ())
+ done = 0, update_insns ();
+
+- if (do_propagate_moves && propagate_moves ())
++ if (do_propagate_moves && opt_propagate_moves ())
+ done = 0, update_insns ();
+
+ update_insn_infos ();
+- if (do_const_cmp_to_sub && const_cmp_to_sub ())
++ if (do_const_cmp_to_sub && opt_const_cmp_to_sub ())
+ done = 0, update_insns (), update_insn_infos ();
+
+- if (do_merge_add && merge_add ())
++ if (do_merge_add && opt_merge_add ())
+ done = 0, update_insns (), update_insn_infos ();
+
+ if (do_elim_dead_assign && elim_dead_assign ())
+@@ -2129,7 +2107,7 @@ namespace
+
+ if (do_shrink_stack_frame)
+ {
+- shrink_stack_frame ();
++ opt_shrink_stack_frame ();
+ update_insns ();
+ update_insn_infos ();
+ }
+
+From cfd147a3142a4e1b6495f4f1c57d2b236c991c95 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 23 Apr 2017 00:05:15 +0200
+Subject: [PATCH 079/303] @N shrink-stack-frame is now also dropping unused
+ frame pointers. @I more cleanup
+
+---
+ gcc/bbb-opts.c | 115 +++++++++++++++++++++++++++++++++++----------------------
+ 1 file changed, 70 insertions(+), 45 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index e7de83e59c07..d684e280a17e 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -367,7 +367,7 @@ temp_reg_rename (std::vector<std::pair<rtx *, rtx>> & loc, rtx x, unsigned oldre
+ * Collect some data.
+ */
+ static std::vector<rtx_insn *> insns;
+-static std::vector<bool> proepilogue;
++static std::vector<char> proepilogue;
+ static std::vector<rtx_insn *> temp;
+ static std::vector<rtx_insn *> jumps;
+ static std::map<rtx_insn *, unsigned> insn2index;
+@@ -477,7 +477,7 @@ update_insns ()
+
+ df_insn_rescan_all ();
+
+- bool inproepilogue = true;
++ char inproepilogue = 1;
+ /* create a vector with relevant insn. */
+ for (insn = get_insns (); insn; insn = next)
+ {
+@@ -493,32 +493,34 @@ update_insns ()
+ proepilogue.push_back (inproepilogue);
+
+ if (JUMP_P(insn))
+- inproepilogue = false;
++ inproepilogue = 0;
+ }
+
+ if (NOTE_P(insn))
+ {
+ if (NOTE_KIND(insn) == NOTE_INSN_PROLOGUE_END)
+- inproepilogue = false;
++ inproepilogue = 0;
+ else if (NOTE_KIND(insn) == NOTE_INSN_EPILOGUE_BEG)
+- inproepilogue = true;
++ inproepilogue = 2;
+ }
+ }
+ }
+
++/* This is the important function to track register usage plus hard/live state.
++ *
++ * Start at bottom and work upwards. On all labels trigger all jumps referring to this label.
++ * A set destination into a register is a def. All other register references are an use.
++ * Hard registers cann't be renamed and are mandatory for regparms and asm_operands.
++ */
+ static void
+ update_insn_infos (void)
+ {
+ /* prepare insn_info */
+- insn_info ii0;
+- for (unsigned i = 0; i < insns.size (); ++i)
+- {
+- infos.push_back (ii0);
+- }
++ infos.resize (insns.size ());
+
+ /* own analyze reg life */
+ std::vector<std::pair<unsigned, insn_info>> todo;
+- todo.push_back (std::make_pair (insns.size () - 1, ii0));
++ todo.push_back (std::make_pair (insns.size () - 1, insn_info ()));
+
+ int pass = 0;
+ while (!todo.empty ())
+@@ -531,9 +533,11 @@ update_insn_infos (void)
+ for (int pos = p.first; pos >= 0; --pos)
+ {
+ rtx_insn * insn = insns[pos];
+- if (!insn) // moved to temp for stack frame cleanup
++ /* can be NULL as used in opt_shrink_stack_frame(). */
++ if (!insn)
+ continue;
+
++ /* no new information -> break. */
+ if (pass && infos[pos].contains (ii))
+ break;
+
+@@ -648,6 +652,7 @@ update_insn_infos (void)
+ }
+ }
+
++/* convert the lowest set bit into a register number. */
+ static int
+ bit2regno (unsigned bit)
+ {
+@@ -667,7 +672,7 @@ bit2regno (unsigned bit)
+ * Always prefer lower register numbers within the class.
+ */
+ static unsigned
+-bb_reg_rename (void)
++opt_reg_rename (void)
+ {
+ // dump_insns ("rename", 1);
+ for (unsigned index = 0; index < insns.size (); ++index)
+@@ -738,8 +743,7 @@ bb_reg_rename (void)
+ rtx jmppattern = PATTERN (insn);
+ if (GET_CODE(jmppattern) == PARALLEL)
+ {
+- return 0; /* can't handle yet. */
+-// jmppattern = XVECEXP(jmppattern, 0, 0);
++ return 0; /* can't handle yet. Abort renaming. */
+ }
+
+ rtx jmpsrc = XEXP(jmppattern, 1);
+@@ -788,7 +792,7 @@ bb_reg_rename (void)
+ if (!ok)
+ continue;
+
+- log ("bb_reg_rename %s -> %s (%d locs)\n", reg_names[oldregno], reg_names[newregno], patch.size ());
++ log ("opt_reg_rename %s -> %s (%d locs)\n", reg_names[oldregno], reg_names[newregno], patch.size ());
+
+ /* apply all changes. */
+ for (std::vector<std::pair<rtx *, rtx>>::iterator j = patch.begin (); j != patch.end (); ++j)
+@@ -1470,6 +1474,10 @@ opt_const_cmp_to_sub (void)
+ return change_count;
+ }
+
++/*
++ * Some optimizations (e.g. propagate_moves) might result into an unuses assignment behind the loop.
++ * delete those insns.
++ */
+ static unsigned
+ elim_dead_assign (void)
+ {
+@@ -1570,6 +1578,9 @@ opt_merge_add (void)
+ return change_count;
+ }
+
++/*
++ * Move the insns back from temp to insns.
++ */
+ static void
+ clear_temp ()
+ {
+@@ -1607,6 +1618,7 @@ opt_shrink_stack_frame (void)
+ if (!insns.size ())
+ return 0;
+
++ std::vector<int> a5pos;
+ temp.resize (insns.size ());
+
+ unsigned pos = 0;
+@@ -1622,16 +1634,11 @@ opt_shrink_stack_frame (void)
+ * Move prologue to temp.
+ * Only register push and parallel insn unless its a link a5 are moved.
+ */
+- rtx_insn * prev = get_insns ();
+ for (; pos < insns.size ();)
+ {
+ insn = insns[pos];
+
+- /* check for prologue end. */
+- for (; prev != insn; prev = NEXT_INSN (prev))
+- if (NOTE_P(prev) && NOTE_KIND(prev) == NOTE_INSN_PROLOGUE_END)
+- break;
+- if (prev != insn)
++ if (proepilogue[pos] != 1)
+ break;
+
+ rtx pattern = PATTERN (insn);
+@@ -1642,6 +1649,7 @@ opt_shrink_stack_frame (void)
+ /* ignore link a5 */
+ if (REG_P(dst) && REGNO(dst) == FRAME_POINTER_REGNUM)
+ {
++ a5pos.push_back (pos);
+ usea5 = true;
+ set = XVECEXP(pattern, 0, 2);
+ a5offset = INTVAL(XEXP(SET_SRC(set), 1));
+@@ -1657,6 +1665,9 @@ opt_shrink_stack_frame (void)
+ }
+ if (GET_CODE(pattern) != SET)
+ {
++ /* (set (mem:BLK (scratch) [0 A8]) (unspec:BLK [ ...)) */
++ if (MEM_P(SET_DEST(pattern)) && GET_CODE(SET_SRC(pattern)) == UNSPEC)
++ a5pos.push_back (pos);
+ ++pos;
+ continue;
+ }
+@@ -1701,21 +1712,13 @@ opt_shrink_stack_frame (void)
+
+ unsigned prologueend = pos;
+
+- prev = insn;
+-
+ /* search epilogues - there can be multiple epilogues. */
+ while (pos < insns.size ())
+ {
+ while (pos < insns.size ())
+ {
+- insn = insns[pos];
+- for (; prev != insn; prev = NEXT_INSN (prev))
+- if (NOTE_P(prev) && NOTE_KIND(prev) == NOTE_INSN_EPILOGUE_BEG)
+- break;
+-
+- if (prev != insn)
++ if (proepilogue[pos])
+ break;
+-
+ ++pos;
+ }
+
+@@ -1723,13 +1726,10 @@ opt_shrink_stack_frame (void)
+ for (; pos < insns.size (); ++pos)
+ {
+ insn = insns[pos];
+- if (JUMP_P(insn)) /* return */
+- break;
+-
+- if (LABEL_P(insn))
++ if (JUMP_P(insn) || LABEL_P(insn) || !proepilogue[pos])
+ break;
+
+- /* omitt the frame pointer a5. */
++ /* omit the frame pointer a5. */
+ rtx pattern = PATTERN (insn);
+ if (GET_CODE(pattern) == PARALLEL)
+ {
+@@ -1737,7 +1737,10 @@ opt_shrink_stack_frame (void)
+ rtx dst = SET_DEST(set);
+ /* unlink is last. */
+ if (REG_P(dst) && REGNO(dst) == FRAME_POINTER_REGNUM)
+- break;
++ {
++ a5pos.push_back (pos);
++ break;
++ }
+
+ /* movem. */
+ temp[pos] = insn;
+@@ -1766,7 +1769,6 @@ opt_shrink_stack_frame (void)
+ }
+ }
+ }
+- prev = insn;
+ ++pos;
+ }
+ /* gather usage stats without prologue/epilogue */
+@@ -1989,6 +1991,33 @@ opt_shrink_stack_frame (void)
+ }
+ }
+
++ if (usea5 && a5offset == -4)
++ {
++ for (std::vector<int>::iterator i = a5pos.begin (); i != a5pos.end (); ++i)
++ {
++ temp[*i] = insns[*i];
++ insns[*i] = 0;
++ }
++ update_insn_infos ();
++ insn_info ii;
++ for (unsigned i = 0; i < infos.size (); ++i)
++ {
++ if (proepilogue[i])
++ continue;
++
++ insn_info & jj = infos[i];
++ ii |= jj;
++ }
++ unsigned freemask = ~ii._use;
++
++ if (freemask & (1 << FRAME_POINTER_REGNUM))
++ {
++ log ("dropping unused frame pointer\n");
++ for (std::vector<int>::iterator i = a5pos.begin (); i != a5pos.end (); ++i)
++ SET_INSN_DELETED(temp[*i]);
++ }
++ }
++
+ /* restore stack insns */
+ clear_temp ();
+
+@@ -2000,14 +2029,14 @@ namespace
+
+ const pass_data pass_data_bbb_optimizations =
+ { RTL_PASS, /* type */
+- "bbb", /* name */
++ "bebbo's-optimizers", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_NONE, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+- ( TODO_df_finish | TODO_df_verify), /* todo_flags_finish */
++ 0, /* todo_flags_finish */
+ };
+
+ class pass_bbb_optimizations : public rtl_opt_pass
+@@ -2053,10 +2082,6 @@ namespace
+ unsigned
+ pass_bbb_optimizations::execute_bbb_optimizations (void)
+ {
+- df_set_flags (DF_LR_RUN_DCE + DF_DEFER_INSN_RESCAN);
+- df_note_add_problem ();
+- df_analyze ();
+-
+ be_verbose = strchr (string_bbb_opts, 'v');
+
+ bool do_opt_strcpy = strchr (string_bbb_opts, 's') || strchr (string_bbb_opts, '+');
+@@ -2093,7 +2118,7 @@ namespace
+
+ if (do_bb_reg_rename)
+ {
+- while (bb_reg_rename ())
++ while (opt_reg_rename ())
+ {
+ update_insns ();
+ update_insn_infos ();
+
+From 0461e994f5f13ef6becd36265f33fa8812f25cb3 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 23 Apr 2017 00:12:10 +0200
+Subject: [PATCH 080/303] @V bump version
+
+---
+ gcc/BASE-VER | 2 +-
+ gcc/DATESTAMP | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/BASE-VER b/gcc/BASE-VER
+index 6352d5267189..91eb9361dcd3 100644
+--- gcc/BASE-VER
++++ gcc/BASE-VER
+@@ -1 +1 @@
+-6.3.1b
++6.3.1c
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index e30948e24831..e9793b647365 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170320
++20170423
+
+From 7cf932893a3328d06b1c1eb4c51b9eaf39db8bc1 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 23 Apr 2017 10:57:09 +0200
+Subject: [PATCH 081/303] @B some fixes in opt_reg_rename
+
+---
+ gcc/bbb-opts.c | 23 +++++++++++++----------
+ 1 file changed, 13 insertions(+), 10 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index d684e280a17e..a8122e80998e 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -238,6 +238,8 @@ struct insn_info
+ return false;
+ if (o._use & ~_use)
+ return false;
++ if (o._hard & ~_hard)
++ return false;
+ return true;
+ }
+
+@@ -298,7 +300,7 @@ insn_info::scan (rtx x)
+ scan (SET_SRC(x));
+ int code = GET_CODE(SET_SRC(x));
+ if (code == ASM_OPERANDS)
+- _hard |= _def | _use;
++ _use = _hard |= _def | _use;
+ return;
+ }
+
+@@ -713,16 +715,13 @@ opt_reg_rename (void)
+
+ insn_info & jj = infos[pos];
+
+- /* not used. */
+- if (!(jj._use & toRename))
+- continue;
+-
+ /* marked as hard reg -> invalid rename */
+ if (jj._hard & toRename)
+- {
+- mask = 0;
+- break;
+- }
++ mask = 0;
++
++ /* defined again -> invalid rename */
++ if (jj._def & toRename)
++ mask = 0;
+
+ /* update free regs. */
+ mask &= ~jj._use;
+@@ -730,6 +729,10 @@ opt_reg_rename (void)
+ if (!mask)
+ break;
+
++ /* not used. */
++ if (!(jj._use & toRename))
++ continue;
++
+ found.insert (pos);
+
+ /* follow jump and/or next insn. */
+@@ -1902,7 +1905,7 @@ opt_shrink_stack_frame (void)
+ else
+ {
+ /* pop */
+- if (usea5)
++ if (usea5 && a5offset != -4)
+ {
+ x += REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4;
+ plus = gen_rtx_PLUS(SImode, a5, gen_rtx_CONST_INT (SImode, a5offset + x));
+
+From fbc0890125f5455fbd9947d439f0caab8b0a4e12 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 23 Apr 2017 10:59:12 +0200
+Subject: [PATCH 082/303] @R change template >> to > > for crappy compilers
+
+---
+ gcc/bbb-opts.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index a8122e80998e..90751c4165d3 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -337,7 +337,7 @@ copy_reg (rtx reg, int newregno)
+
+ /* Rename the register plus track all locs to undo these changes. */
+ static void
+-temp_reg_rename (std::vector<std::pair<rtx *, rtx>> & loc, rtx x, unsigned oldregno, unsigned newregno)
++temp_reg_rename (std::vector<std::pair<rtx *, rtx> > & loc, rtx x, unsigned oldregno, unsigned newregno)
+ {
+ RTX_CODE code = GET_CODE(x);
+
+@@ -521,7 +521,7 @@ update_insn_infos (void)
+ infos.resize (insns.size ());
+
+ /* own analyze reg life */
+- std::vector<std::pair<unsigned, insn_info>> todo;
++ std::vector<std::pair<unsigned, insn_info> > todo;
+ todo.push_back (std::make_pair (insns.size () - 1, insn_info ()));
+
+ int pass = 0;
+@@ -764,8 +764,8 @@ opt_reg_rename (void)
+ int newregno = bit2regno (mask);
+
+ /* check the renamed insns. */
+- std::vector<std::pair<rtx *, rtx>> locs;
+- std::vector<std::pair<rtx *, rtx>> patch;
++ std::vector<std::pair<rtx *, rtx> > locs;
++ std::vector<std::pair<rtx *, rtx> > patch;
+ bool ok = true;
+
+ for (std::set<unsigned>::iterator i = found.begin (); ok && i != found.end (); ++i)
+@@ -782,7 +782,7 @@ opt_reg_rename (void)
+ ok = false;
+
+ /* undo temp change but keep loc and new register. */
+- for (std::vector<std::pair<rtx *, rtx>>::iterator j = locs.begin (); j != locs.end (); ++j)
++ for (std::vector<std::pair<rtx *, rtx> >::iterator j = locs.begin (); j != locs.end (); ++j)
+ {
+ patch.push_back (std::make_pair (j->first, *j->first));
+ *j->first = j->second;
+@@ -798,7 +798,7 @@ opt_reg_rename (void)
+ log ("opt_reg_rename %s -> %s (%d locs)\n", reg_names[oldregno], reg_names[newregno], patch.size ());
+
+ /* apply all changes. */
+- for (std::vector<std::pair<rtx *, rtx>>::iterator j = patch.begin (); j != patch.end (); ++j)
++ for (std::vector<std::pair<rtx *, rtx> >::iterator j = patch.begin (); j != patch.end (); ++j)
+ *j->first = j->second;
+
+ return 1;
+
+From d98fb77f2e7d620cb8c901f806e8d938b3e7f07f Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 23 Apr 2017 13:38:06 +0200
+Subject: [PATCH 083/303] @B init insn_infos before running opt_strcpy
+
+---
+ gcc/bbb-opts.c | 35 +++++++++++++++++++----------------
+ 1 file changed, 19 insertions(+), 16 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 90751c4165d3..2858daa6c908 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -390,24 +390,23 @@ clear (void)
+
+ /*
+ * return true if the register is DEAD.
++ * Do not check at jumps.
+ */
+ static bool
+-is_reg_dead (unsigned regno, unsigned pos)
++is_reg_dead (unsigned regno, unsigned _pos)
+ {
+- for (;;)
++ // skip labels.
++ for (unsigned pos = _pos + 1; pos < infos.size (); ++pos)
+ {
+- if (pos + 1 >= infos.size ())
+- return true;
++ insn_info & ii0 = infos[pos];
++ // skip entries without info
++ if (!ii0._def && !ii0._use && !ii0._hard)
++ continue;
+
+- rtx_insn * insn = insns[pos + 1];
+- if (!LABEL_P(insn) && GET_CODE(insn) != USE)
+- break;
+- ++pos;
++ // not dead if usage is reported in the next statement
++ return !ii0.is_use (regno) && !ii0.is_hard (regno);
+ }
+-
+- insn_info & ii0 = infos[pos + 1];
+- // not dead if usage is reported in the next statement
+- return !ii0.is_use (regno);
++ return true;
+ }
+
+ /*
+@@ -720,12 +719,9 @@ opt_reg_rename (void)
+ mask = 0;
+
+ /* defined again -> invalid rename */
+- if (jj._def & toRename)
++ if ((jj._def & toRename) && !(jj._use & toRename))
+ mask = 0;
+
+- /* update free regs. */
+- mask &= ~jj._use;
+- mask &= ~jj._def;
+ if (!mask)
+ break;
+
+@@ -733,6 +729,12 @@ opt_reg_rename (void)
+ if (!(jj._use & toRename))
+ continue;
+
++ /* update free regs. */
++ mask &= ~jj._use;
++ mask &= ~jj._def;
++ if (!mask)
++ break;
++
+ found.insert (pos);
+
+ /* follow jump and/or next insn. */
+@@ -2100,6 +2102,7 @@ namespace
+ {
+ int done = 1;
+ update_insns ();
++ update_insn_infos ();
+ if (do_opt_strcpy && opt_strcpy ())
+ done = 0, update_insns ();
+
+
+From 78db2bc90ad5701e59107a782343b1d25937102e Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 23 Apr 2017 23:08:07 +0200
+Subject: [PATCH 084/303] @B fix regparm with return values > 64bit
+
+---
+ gcc/config/m68k/amigaos.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index dd5707612119..d385ab1ff108 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -435,6 +435,15 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl)
+ if (!next_param && TREE_VALUE (param) != void_type_node)
+ cum->num_of_regs = 0;
+ }
++
++ /* check for return values passed in a0 */
++ if (cum->num_of_regs)
++ {
++ tree type = TYPE_SIZE(TREE_TYPE (DECL_RESULT (current_function_decl)));
++ int sz = type ? TREE_INT_CST_LOW(type) : 0;
++ if (sz > 64) /* mark a0 as already used. */
++ cum->regs_already_used |= 1<<8;
++ }
+ }
+
+ //#if ! defined (PCC_STATIC_STRUCT_RETURN) && defined (M68K_STRUCT_VALUE_REGNUM)
+
+From 5c0207b6ae6544541c786c74d57ddfcbe48b7a48 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 23 Apr 2017 23:08:48 +0200
+Subject: [PATCH 085/303] @B fix __regards definition
+
+---
+ gcc/config/m68k/m68kamigaos.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h
+index 68f3277bd87c..20e0b66face2 100644
+--- gcc/config/m68k/m68kamigaos.h
++++ gcc/config/m68k/m68kamigaos.h
+@@ -194,7 +194,7 @@ amiga_declare_object = 0
+ builtin_define ("__saveds=__attribute__((__saveds__))"); \
+ builtin_define ("__interrupt=__attribute__((__interrupt__))"); \
+ builtin_define ("__stackext=__attribute__((__stackext__))"); \
+- builtin_define ("__regargs=__attribute__((__regparm__))"); \
++ builtin_define ("__regargs=__attribute__((__regparm__(2)))"); \
+ builtin_define ("__stdargs=__attribute__((__stkparm__))"); \
+ builtin_define ("__aligned=__attribute__((__aligned__(4)))"); \
+ builtin_define_std ("amiga"); \
+
+From 827a96ae044a2b7925972b04ec8e24c0999daa71 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 23 Apr 2017 23:09:27 +0200
+Subject: [PATCH 086/303] @B fix return val sizes and so...
+
+---
+ gcc/bbb-opts.c | 55 +++++++++++++++++++++++++++++++++++++------------------
+ 1 file changed, 37 insertions(+), 18 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 2858daa6c908..d0288f254f9c 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -476,7 +476,7 @@ update_insns ()
+ rtx_insn *insn, *next;
+ clear ();
+
+- df_insn_rescan_all ();
++ // df_insn_rescan_all ();
+
+ char inproepilogue = 1;
+ /* create a vector with relevant insn. */
+@@ -593,10 +593,25 @@ update_insn_infos (void)
+
+ if (JUMP_P(insn))
+ {
++ insn_info use;
+ if (ANY_RETURN_P(pattern))
+- ii.reset ();
++ {
++ tree type = TYPE_SIZE(TREE_TYPE (DECL_RESULT (current_function_decl)));
++ int sz = type ? TREE_INT_CST_LOW(type) : 0;
++ // log ("return size %d\n", sz);
++ if (sz <= 64)
++ {
++ use.hard (0);
++ use.use (0);
++ if (sz > 32)
++ {
++ use.hard (1);
++ use.use (1);
++ }
++ }
++ ii.reset ();
++ }
+
+- insn_info use;
+ use.scan (pattern);
+ infos[pos] = use | ii;
+ ii.updateWith (use);
+@@ -752,7 +767,7 @@ opt_reg_rename (void)
+ }
+
+ rtx jmpsrc = XEXP(jmppattern, 1);
+- if (GET_CODE(jmpsrc) == IF_THEN_ELSE)
++ if (jmpsrc && GET_CODE(jmpsrc) == IF_THEN_ELSE)
+ if (pos + 1 < insns.size ())
+ todo.push_back (pos + 1);
+ }
+@@ -1065,8 +1080,8 @@ opt_propagate_moves ()
+ j = reg_reg.end ();
+ inc = false;
+
+- df_insn_rescan (newii);
+- df_insn_rescan (newjj);
++ // df_insn_rescan (newii);
++ // df_insn_rescan (newjj);
+
+ /* add fixes if there were jumps out of the loop. */
+ if (jump_out.size ())
+@@ -1078,7 +1093,7 @@ opt_propagate_moves ()
+ rtx neu = gen_rtx_SET(
+ dstj, gen_rtx_PLUS(Pmode, dsti, gen_rtx_CONST_INT(Pmode, fixups[k])));
+ rtx_insn * neui = emit_insn_after (neu, jump_out[k]);
+- df_insn_rescan (neui);
++ // df_insn_rescan (neui);
+ }
+ }
+ ++change_count;
+@@ -1178,7 +1193,7 @@ opt_strcpy ()
+ SET_INSN_DELETED(x2reg);
+ SET_INSN_DELETED(insn);
+
+- df_insn_rescan (reg2x);
++ // df_insn_rescan (reg2x);
+
+ ++change_count;
+ }
+@@ -1238,7 +1253,7 @@ opt_strcpy ()
+ (nil)))
+ */
+ static unsigned
+-commute_add_move (void)
++opt_commute_add_move (void)
+ {
+ unsigned change_count = 0;
+
+@@ -1295,8 +1310,8 @@ commute_add_move (void)
+
+ add_reg_note (next, REG_INC, reg1dst);
+
+- df_insn_rescan (insn);
+- df_insn_rescan (next);
++ // df_insn_rescan (insn);
++ // df_insn_rescan (next);
+
+ ++change_count;
+ }
+@@ -1484,7 +1499,7 @@ opt_const_cmp_to_sub (void)
+ * delete those insns.
+ */
+ static unsigned
+-elim_dead_assign (void)
++opt_elim_dead_assign (void)
+ {
+ unsigned change_count = 0;
+ for (unsigned index = 0; index + 1 < insns.size (); ++index)
+@@ -1835,7 +1850,7 @@ opt_shrink_stack_frame (void)
+ adjust += 4;
+ }
+ else
+- regs.push_back (reg);
++ regs.push_back (copy_reg (reg, -1));
+ }
+
+ /* don't touch - clobbers! */
+@@ -1907,7 +1922,7 @@ opt_shrink_stack_frame (void)
+ else
+ {
+ /* pop */
+- if (usea5 && a5offset != -4)
++ if (usea5)
+ {
+ x += REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4;
+ plus = gen_rtx_PLUS(SImode, a5, gen_rtx_CONST_INT (SImode, a5offset + x));
+@@ -2041,8 +2056,8 @@ namespace
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+- 0, /* todo_flags_finish */
+- };
++ 0, //( TODO_df_finish | TODO_df_verify), /* todo_flags_finish */
++ };
+
+ class pass_bbb_optimizations : public rtl_opt_pass
+ {
+@@ -2087,6 +2102,10 @@ namespace
+ unsigned
+ pass_bbb_optimizations::execute_bbb_optimizations (void)
+ {
++ // df_set_flags (df_LR_RUN_DCE + df_DEFER_INSN_RESCAN);
++ // df_note_add_problem ();
++ // df_analyze ();
++
+ be_verbose = strchr (string_bbb_opts, 'v');
+
+ bool do_opt_strcpy = strchr (string_bbb_opts, 's') || strchr (string_bbb_opts, '+');
+@@ -2106,7 +2125,7 @@ namespace
+ if (do_opt_strcpy && opt_strcpy ())
+ done = 0, update_insns ();
+
+- if (do_commute_add_move && commute_add_move ())
++ if (do_commute_add_move && opt_commute_add_move ())
+ done = 0, update_insns ();
+
+ if (do_propagate_moves && opt_propagate_moves ())
+@@ -2119,7 +2138,7 @@ namespace
+ if (do_merge_add && opt_merge_add ())
+ done = 0, update_insns (), update_insn_infos ();
+
+- if (do_elim_dead_assign && elim_dead_assign ())
++ if (do_elim_dead_assign && opt_elim_dead_assign ())
+ done = 0, update_insns (), update_insn_infos ();
+
+ if (do_bb_reg_rename)
+
+From e0bc074377aadb67fd623bd92a28c6938a53c557 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 24 Apr 2017 01:07:46 +0200
+Subject: [PATCH 087/303] @B fix mregparm for function pointer calls
+
+---
+ gcc/config/m68k/amigaos.c | 569 +++++++++++++++++++++++-----------------------
+ 1 file changed, 280 insertions(+), 289 deletions(-)
+
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index d385ab1ff108..c93188a3e90d 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -1,25 +1,25 @@
+ /* Configuration for GNU C-compiler for m68k Amiga, running AmigaOS.
+- Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2003
+- Free Software Foundation, Inc.
+- Contributed by Markus M. Wild (wild@amiga.physik.unizh.ch).
+- Heavily modified by Kamil Iskra (iskra@student.uci.agh.edu.pl).
++ Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2003
++ Free Software Foundation, Inc.
++ Contributed by Markus M. Wild (wild@amiga.physik.unizh.ch).
++ Heavily modified by Kamil Iskra (iskra@student.uci.agh.edu.pl).
+
+-This file is part of GCC.
++ This file is part of GCC.
+
+-GCC 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.
++ GCC 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.
+
+-GCC 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.
++ GCC 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 GCC; see the file COPYING. If not, write to
+-the Free Software Foundation, 59 Temple Place - Suite 330,
+-Boston, MA 02111-1307, USA. */
++ You should have received a copy of the GNU General Public License
++ along with GCC; see the file COPYING. If not, write to
++ the Free Software Foundation, 59 Temple Place - Suite 330,
++ Boston, MA 02111-1307, USA. */
+
+ //work without flag_writable_strings which is not in GCC4
+ #define REGPARMS_68K 1
+@@ -38,6 +38,7 @@ Boston, MA 02111-1307, USA. */
+ #include "tm_p.h"
+ #include "target.h"
+ #include "diagnostic-core.h"
++#include "langhooks.h"
+ #include "config/m68k/amigaos.h"
+
+ //#define MYDEBUG 1
+@@ -56,28 +57,28 @@ static rtx gen_stack_management_call (rtx, rtx, const char *);
+ /* Baserel support. */
+
+ /* Does operand (which is a symbolic_operand) live in text space? If
+- so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true.
++ so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true.
+
+- This function is used in base relative code generation. */
++ This function is used in base relative code generation. */
+
+ int
+ read_only_operand (rtx operand)
+-{
+- if (GET_CODE (operand) == CONST)
++ {
++ if (GET_CODE (operand) == CONST)
+ operand = XEXP (XEXP (operand, 0), 0);
+- if (GET_CODE (operand) == SYMBOL_REF)
++ if (GET_CODE (operand) == SYMBOL_REF)
+ return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand);
+- return 1;
+-}
++ return 1;
++ }
+
+ /* Choose the section to use for DECL. RELOC is true if its value contains
+- any relocatable expression. */
++ any relocatable expression. */
+
+ void
+ amigaos_select_section (tree decl ATTRIBUTE_UNUSED, int reloc ATTRIBUTE_UNUSED,
+- unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
+-{
+- // if (TREE_CODE (decl) == STRING_CST)
++ unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
++ {
++ // if (TREE_CODE (decl) == STRING_CST)
+ // {
+ //// flag_writable_strings /data_section not in gcc4,
+ ////make life easy and put to same section
+@@ -104,195 +105,189 @@ amigaos_select_section (tree decl ATTRIBUTE_UNUSED, int reloc ATTRIBUTE_UNUSED,
+ // readonly_data_section ();
+ // else
+ //data_section ();
+-}
++ }
+
+ /* This function is used while generating a base relative code.
+- It returns 1 if a decl is not relocatable, i. e., if it can be put
+- in the text section.
+- Currently, it's very primitive: it just checks if the object size
+- is less than 4 bytes (i. e., if it can hold a pointer). It also
+- supports arrays and floating point types. */
++ It returns 1 if a decl is not relocatable, i. e., if it can be put
++ in the text section.
++ Currently, it's very primitive: it just checks if the object size
++ is less than 4 bytes (i. e., if it can hold a pointer). It also
++ supports arrays and floating point types. */
+
+ static int
+ amigaos_put_in_text (tree decl)
+-{
+- tree type = TREE_TYPE (decl);
+- if (TREE_CODE (type) == ARRAY_TYPE)
++ {
++ tree type = TREE_TYPE (decl);
++ if (TREE_CODE (type) == ARRAY_TYPE)
+ type = TREE_TYPE (type);
+- return (TREE_INT_CST_ELT(TYPE_SIZE (type), 1) == 0
+- && TREE_INT_CST_LOW (TYPE_SIZE (type)) < 32)
+- || FLOAT_TYPE_P (type);
+-}
++ return (TREE_INT_CST_ELT(TYPE_SIZE (type), 1) == 0
++ && TREE_INT_CST_LOW (TYPE_SIZE (type)) < 32)
++ || FLOAT_TYPE_P (type);
++ }
+
+ /* Record properties of a DECL into the associated SYMBOL_REF. */
+
+ void
+ amigaos_encode_section_info (tree decl, rtx rtl, int first)
+-{
+- default_encode_section_info (decl, rtl, first);
++ {
++ default_encode_section_info (decl, rtl, first);
+
+-
+- SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
+- if (TREE_CODE (decl) == FUNCTION_DECL) // huh seem do same. not in gcc4 flag_writable_strings
+ SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
+- else
+- {
+- if ((MEM_READONLY_P (rtl) && !MEM_VOLATILE_P (rtl)
+- && (flag_pic<3 || (TREE_CODE (decl) == STRING_CST
+- )
+- || amigaos_put_in_text (decl)))
+- || (TREE_CODE (decl) == VAR_DECL
+- && DECL_SECTION_NAME (decl) != NULL))
+- SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
+- }
+-}
++ if (TREE_CODE (decl) == FUNCTION_DECL) // huh seem do same. not in gcc4 flag_writable_strings
++ SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
++ else
++ {
++ if ((MEM_READONLY_P (rtl) && !MEM_VOLATILE_P (rtl)
++ && (flag_pic<3 || (TREE_CODE (decl) == STRING_CST
++ )
++ || amigaos_put_in_text (decl)))
++ || (TREE_CODE (decl) == VAR_DECL
++ && DECL_SECTION_NAME (decl) != NULL))
++ SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
++ }
++ }
+
+ /* Common routine used to check if a4 should be preserved/restored. */
+
+ int
+ amigaos_restore_a4 (void)
+-{
+- return (flag_pic >= 3 &&
+- (TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4
+- || lookup_attribute ("saveds",
+- TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))));
+-}
++ {
++ return (flag_pic >= 3 &&
++ (TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4
++ || lookup_attribute ("saveds",
++ TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))));
++ }
+
+ void
+ amigaos_alternate_pic_setup (FILE *stream)
+-{
+- if (TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4)
++ {
++ if (TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4)
+ asm_fprintf (stream, "\tjbsr %U__restore_a4\n");
+- else if (lookup_attribute ("saveds",
+- TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
++ else if (lookup_attribute ("saveds",
++ TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
+ asm_fprintf (stream, "\tlea %U__a4_init,%Ra4\n");
+-}
++ }
+
+ /* Attributes support. */
+
+ #define AMIGA_CHIP_SECTION_NAME ".datachip"
+
+ /* Handle a "chip" attribute;
+- arguments as in struct attribute_spec.handler. */
++ arguments as in struct attribute_spec.handler. */
+
+ tree
+ amigaos_handle_decl_attribute (tree *node, tree name,
+- tree args ATTRIBUTE_UNUSED,
+- int flags ATTRIBUTE_UNUSED,
+- bool *no_add_attrs)
+-{
+- if (TREE_CODE (*node) == VAR_DECL)
+- {
+- if (is_attribute_p ("chip", name))
++ tree args ATTRIBUTE_UNUSED,
++ int flags ATTRIBUTE_UNUSED,
++ bool *no_add_attrs)
++ {
++ if (TREE_CODE (*node) == VAR_DECL)
++ {
++ if (is_attribute_p ("chip", name))
+ #ifdef TARGET_ASM_NAMED_SECTION
+- {
+- if (! TREE_STATIC (*node) && ! DECL_EXTERNAL (*node))
++ {
++ if (! TREE_STATIC (*node) && ! DECL_EXTERNAL (*node))
+ error ("`chip' attribute cannot be specified for local variables");
+- else
+- {
+- /* The decl may have already been given a section attribute from
+- a previous declaration. Ensure they match. */
+- if (DECL_SECTION_NAME (*node) == NULL_TREE)
+- DECL_SECTION_NAME (*node) =
+- build_string (strlen (AMIGA_CHIP_SECTION_NAME) + 1,
+- AMIGA_CHIP_SECTION_NAME);
+- else if (strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (*node)),
+- AMIGA_CHIP_SECTION_NAME) != 0)
+- {
+- error_with_decl (*node,
+- "`chip' for `%s' conflicts with previous declaration");
+- }
+- }
+- }
++ else
++ {
++ /* The decl may have already been given a section attribute from
++ a previous declaration. Ensure they match. */
++ if (DECL_SECTION_NAME (*node) == NULL_TREE)
++ DECL_SECTION_NAME (*node) =
++ build_string (strlen (AMIGA_CHIP_SECTION_NAME) + 1,
++ AMIGA_CHIP_SECTION_NAME);
++ else if (strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (*node)),
++ AMIGA_CHIP_SECTION_NAME) != 0)
++ {
++ error_with_decl (*node,
++ "`chip' for `%s' conflicts with previous declaration");
++ }
++ }
++ }
+ #else
+- error ("`chip' attribute is not supported for this target");
++ error ("`chip' attribute is not supported for this target");
+ #endif
+- }
+- else
+- {
+- warning (OPT_Wattributes, "`%s' attribute only applies to variables",
+- IDENTIFIER_POINTER (name));
+- *no_add_attrs = true;
+- }
++ }
++ else
++ {
++ warning (OPT_Wattributes, "`%s' attribute only applies to variables",
++ IDENTIFIER_POINTER (name));
++ *no_add_attrs = true;
++ }
+
+- return NULL_TREE;
+-}
++ return NULL_TREE;
++ }
+
+ //----- from 68k.c start
+
+-
+-
+-
+-
+-
+ /* Stack checking and automatic extension support. */
+
+ void
+ amigaos_prologue_begin_hook (FILE *stream, int fsize)
+-{
+- if (TARGET_STACKCHECK)
+- {
+- if (fsize < 256)
++ {
++ if (TARGET_STACKCHECK)
++ {
++ if (fsize < 256)
+ asm_fprintf (stream, "\tcmpl %s,%Rsp\n"
+- "\tjcc 0f\n"
+- "\tjra %U__stkovf\n"
+- "\t0:\n",
+- (flag_pic == 3 ? "a4@(___stk_limit:W)" :
+- (flag_pic == 4 ? "a4@(___stk_limit:L)" :
+- "___stk_limit")));
+- else
++ "\tjcc 0f\n"
++ "\tjra %U__stkovf\n"
++ "\t0:\n",
++ (flag_pic == 3 ? "a4@(___stk_limit:W)" :
++ (flag_pic == 4 ? "a4@(___stk_limit:L)" :
++ "___stk_limit")));
++ else
+ asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__stkchk_d0\n",
+- fsize);
+- }
+-}
++ fsize);
++ }
++ }
+
+ void
+ amigaos_alternate_frame_setup_f (FILE *stream, int fsize)
+-{
+- if (fsize < 128)
++ {
++ if (fsize < 128)
+ asm_fprintf (stream, "\tcmpl %s,%Rsp\n"
+- "\tjcc 0f\n"
+- "\tmoveq %I%d,%Rd0\n"
+- "\tmoveq %I0,%Rd1\n"
+- "\tjbsr %U__stkext_f\n"
+- "0:\tlink %Ra5,%I%d:W\n",
+- (flag_pic == 3 ? "a4@(___stk_limit:W)" :
+- (flag_pic == 4 ? "a4@(___stk_limit:L)" :
+- "___stk_limit")),
+- fsize, -fsize);
+- else
++ "\tjcc 0f\n"
++ "\tmoveq %I%d,%Rd0\n"
++ "\tmoveq %I0,%Rd1\n"
++ "\tjbsr %U__stkext_f\n"
++ "0:\tlink %Ra5,%I%d:W\n",
++ (flag_pic == 3 ? "a4@(___stk_limit:W)" :
++ (flag_pic == 4 ? "a4@(___stk_limit:L)" :
++ "___stk_limit")),
++ fsize, -fsize);
++ else
+ asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__link_a5_d0_f\n",
+- fsize);
+-}
++ fsize);
++ }
+
+ void
+ amigaos_alternate_frame_setup (FILE *stream, int fsize)
+-{
+- if (!fsize)
++ {
++ if (!fsize)
+ asm_fprintf (stream, "\tcmpl %s,%Rsp\n"
+- "\tjcc 0f\n"
+- "\tmoveq %I0,%Rd0\n"
+- "\tmoveq %I0,%Rd1\n"
+- "\tjbsr %U__stkext_f\n"
+- "0:\n",
+- (flag_pic == 3 ? "a4@(___stk_limit:W)" :
+- (flag_pic == 4 ? "a4@(___stk_limit:L)" :
+- "___stk_limit")));
+- else if (fsize < 128)
++ "\tjcc 0f\n"
++ "\tmoveq %I0,%Rd0\n"
++ "\tmoveq %I0,%Rd1\n"
++ "\tjbsr %U__stkext_f\n"
++ "0:\n",
++ (flag_pic == 3 ? "a4@(___stk_limit:W)" :
++ (flag_pic == 4 ? "a4@(___stk_limit:L)" :
++ "___stk_limit")));
++ else if (fsize < 128)
+ asm_fprintf (stream, "\tcmpl %s,%Rsp\n"
+- "\tjcc 0f\n"
+- "\tmoveq %I%d,%Rd0\n"
+- "\tmoveq %I0,%Rd1\n"
+- "\tjbsr %U__stkext_f\n"
+- "0:\taddw %I%d,%Rsp\n",
+- (flag_pic == 3 ? "a4@(___stk_limit:W)" :
+- (flag_pic == 4 ? "a4@(___stk_limit:L)" :
+- "___stk_limit")),
+- fsize, -fsize);
+- else
++ "\tjcc 0f\n"
++ "\tmoveq %I%d,%Rd0\n"
++ "\tmoveq %I0,%Rd1\n"
++ "\tjbsr %U__stkext_f\n"
++ "0:\taddw %I%d,%Rsp\n",
++ (flag_pic == 3 ? "a4@(___stk_limit:W)" :
++ (flag_pic == 4 ? "a4@(___stk_limit:L)" :
++ "___stk_limit")),
++ fsize, -fsize);
++ else
+ asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__sub_d0_sp_f\n",
+- fsize);
+-}
++ fsize);
++ }
+
+ //static rtx
+ //gen_stack_management_call (rtx stack_pointer, rtx arg, const char *func)
+@@ -385,7 +380,8 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl)
+ struct amigaos_args * cum = decl == current_function_decl ? &mycum : &othercum;
+ *cump = decl == current_function_decl;
+ cum->num_of_regs = amigaos_regparm > 0 ? amigaos_regparm : 0;
+- DPRINTF(("0amigaos_init_cumulative_args %p -> %d\r\n", cum, cum->num_of_regs));
++ DPRINTF(
++ ("0amigaos_init_cumulative_args %s %p -> %d\r\n", decl ? lang_hooks.decl_printable_name (decl, 2) : "?", cum, cum->num_of_regs));
+
+ /* Initialize a variable CUM of type CUMULATIVE_ARGS
+ for a call to a function whose data type is FNTYPE.
+@@ -394,28 +390,32 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl)
+ cum->last_arg_reg = -1;
+ cum->regs_already_used = 0;
+
+- if (decl)
++ if (fntype)
+ {
+- tree attrs = DECL_ATTRIBUTES(decl);
+- if (lookup_attribute ("stkparm", attrs))
+- cum->num_of_regs = 0;
+- else
++ tree attrs = decl ? DECL_ATTRIBUTES(decl) : NULL;
++ if (attrs)
+ {
+- tree ratree = lookup_attribute ("regparm", attrs);
+- cum->num_of_regs = amigaos_regparm != 0 ?
+- amigaos_regparm : AMIGAOS_DEFAULT_REGPARM;
+- if (ratree)
++ if (lookup_attribute ("stkparm", attrs))
++ cum->num_of_regs = 0;
++ else
+ {
+- tree args = TREE_VALUE(ratree);
+-
+- if (args && TREE_CODE (args) == TREE_LIST)
++ tree ratree = lookup_attribute ("regparm", attrs);
++ cum->num_of_regs = amigaos_regparm != 0 ?
++ amigaos_regparm :
++ AMIGAOS_DEFAULT_REGPARM;
++ if (ratree)
+ {
+- tree val = TREE_VALUE(args);
+- if (TREE_CODE (val) == INTEGER_CST)
++ tree args = TREE_VALUE(ratree);
++
++ if (args && TREE_CODE (args) == TREE_LIST)
+ {
+- int no = TREE_INT_CST_LOW(val);
+- if (no > 0 && no < AMIGAOS_MAX_REGPARM)
+- cum->num_of_regs = no;
++ tree val = TREE_VALUE(args);
++ if (TREE_CODE (val) == INTEGER_CST)
++ {
++ int no = TREE_INT_CST_LOW(val);
++ if (no > 0 && no < AMIGAOS_MAX_REGPARM)
++ cum->num_of_regs = no;
++ }
+ }
+ }
+ }
+@@ -442,7 +442,7 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl)
+ tree type = TYPE_SIZE(TREE_TYPE (DECL_RESULT (current_function_decl)));
+ int sz = type ? TREE_INT_CST_LOW(type) : 0;
+ if (sz > 64) /* mark a0 as already used. */
+- cum->regs_already_used |= 1<<8;
++ cum->regs_already_used |= 1 << 8;
+ }
+ }
+
+@@ -465,13 +465,12 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl)
+ /* Update the data in CUM to advance over an argument. */
+
+ void
+-amigaos_function_arg_advance (cumulative_args_t cum_v, machine_mode, const_tree,
+- bool)
++amigaos_function_arg_advance (cumulative_args_t cum_v, machine_mode, const_tree, bool)
+ {
+ struct amigaos_args *cum = *get_cumulative_args (cum_v) ? &mycum : &othercum;
+ /* Update the data in CUM to advance over an argument. */
+
+- DPRINTF(("amigaos_function_arg_advance1 %p\r\n", cump));
++ DPRINTF(("amigaos_function_arg_advance1 %p\r\n", cum));
+
+ if (cum->last_arg_reg != -1)
+ {
+@@ -507,8 +506,7 @@ _m68k_function_arg (struct amigaos_args * cum, machine_mode mode, const_tree typ
+
+ /* FIXME: The last condition below is a workaround for a bug. */
+ if (TARGET_68881 && FLOAT_MODE_P(mode) &&
+- GET_MODE_UNIT_SIZE (mode) <= 12
+- && (GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT || mode == SCmode))
++ GET_MODE_UNIT_SIZE (mode) <= 12 && (GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT || mode == SCmode))
+ {
+ regbegin = 16; /* FPx */
+ len = GET_MODE_NUNITS(mode);
+@@ -534,8 +532,7 @@ _m68k_function_arg (struct amigaos_args * cum, machine_mode mode, const_tree typ
+ if (!(cum->regs_already_used & mask))
+ {
+ int end;
+- for (end = reg; end < cum->num_of_regs && end < reg + len;
+- end++, mask <<= 1)
++ for (end = reg; end < cum->num_of_regs && end < reg + len; end++, mask <<= 1)
+ if (cum->regs_already_used & mask)
+ break;
+ if (end == reg + len)
+@@ -546,7 +543,7 @@ _m68k_function_arg (struct amigaos_args * cum, machine_mode mode, const_tree typ
+ }
+ }
+
+- if (reg == cum->num_of_regs && altregbegin != -1)
++ if (reg == cum->num_of_regs && altregbegin != -1)
+ {
+ DPRINTF(("look for alt reg\n"));
+ regbegin = altregbegin;
+@@ -568,14 +565,15 @@ _m68k_function_arg (struct amigaos_args * cum, machine_mode mode, const_tree typ
+ in a register, and which register. */
+
+ struct rtx_def *
+-amigaos_function_arg (cumulative_args_t cum_v, machine_mode mode,
+- const_tree type, bool)
++amigaos_function_arg (cumulative_args_t cum_v, machine_mode mode, const_tree type, bool)
+ {
+ DPRINTF(("amigaos_function_arg %p\r\n", cum_v.p));
+
+ struct amigaos_args *cum = *get_cumulative_args (cum_v) ? &mycum : &othercum;
+
+- tree asmtree = type ? TYPE_ATTRIBUTES(type) : NULL_TREE;
++ tree asmtree = type ? TYPE_ATTRIBUTES(cum->formal_type ? TREE_VALUE(cum->formal_type) : type) : NULL_TREE;
++ //tree asmtree = type ? TYPE_ATTRIBUTES(type) : NULL_TREE;
++
+ if (asmtree && 0 == strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(asmtree))))
+ {
+ int i;
+@@ -596,18 +594,18 @@ amigaos_function_arg (cumulative_args_t cum_v, machine_mode mode,
+ return _m68k_function_arg (cum, mode, type);
+ }
+
+-void amiga_emit_regparm_clobbers(void)
++void
++amiga_emit_regparm_clobbers (void)
+ {
+- rtx sp = gen_raw_REG(Pmode, 15);
++ rtx sp = gen_raw_REG (Pmode, 15);
+ for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+ if (mycum.regs_already_used & (1 << i))
+ {
+- rtx reg = gen_raw_REG(Pmode, i);
+- emit_insn(gen_rtx_CLOBBER(Pmode, gen_rtx_SET(reg, gen_rtx_MEM(Pmode, reg))));
++ rtx reg = gen_raw_REG (Pmode, i);
++ emit_insn (gen_rtx_CLOBBER(Pmode, gen_rtx_SET(reg, gen_rtx_MEM(Pmode, reg))));
+ }
+ }
+
+-
+ /* Return zero if the attributes on TYPE1 and TYPE2 are incompatible,
+ one if they are compatible, and two if they are nearly compatible
+ (which causes a warning to be generated). */
+@@ -633,8 +631,7 @@ amigaos_comp_type_attributes (const_tree type1, const_tree type2)
+ attr2 = NULL_TREE;
+ if (attr1 && attr2)
+ {
+- if (TREE_FIXED_CST_PTR(TREE_VALUE(attr1))->data.low
+- != TREE_FIXED_CST_PTR(TREE_VALUE(attr2))->data.low)
++ if (TREE_FIXED_CST_PTR(TREE_VALUE(attr1))->data.low != TREE_FIXED_CST_PTR(TREE_VALUE(attr2))->data.low)
+ return 0;
+ }
+ else if (attr1 || attr2)
+@@ -647,140 +644,135 @@ amigaos_comp_type_attributes (const_tree type1, const_tree type2)
+ }
+
+ /* Return zero if the attributes on TYPE1 and TYPE2 are incompatible,
+- one if they are compatible, and two if they are nearly compatible
+- (which causes a warning to be generated). */
++ one if they are compatible, and two if they are nearly compatible
++ (which causes a warning to be generated). */
+ #if 0
+ static int
+ m68k_comp_type_attributes (tree type1, tree type2)
+-{
++ {
+
+- /* Functions or methods are incompatible if they specify mutually
++ /* Functions or methods are incompatible if they specify mutually
+ exclusive ways of passing arguments. */
+- if (TREE_CODE (type1) == FUNCTION_TYPE || TREE_CODE (type1) == METHOD_TYPE)
+- {
+- tree arg1, arg2;
+- if (!! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type1)) !=
+- !! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type2))
+- || !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1)) !=
+- !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2)))
++ if (TREE_CODE (type1) == FUNCTION_TYPE || TREE_CODE (type1) == METHOD_TYPE)
++ {
++ tree arg1, arg2;
++ if (!! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type1)) !=
++ !! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type2))
++ || !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1)) !=
++ !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2)))
+ return 0; /* 'regparm' and 'stkparm' are mutually exclusive. */
+
+- arg1 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1));
+- arg2 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2));
+- if (arg1 && arg2)
+- {
+- int num1 = 0, num2 = 0;
+- if (TREE_VALUE (arg1) && TREE_CODE (TREE_VALUE (arg1)) == TREE_LIST)
+- {
+- tree numofregs = TREE_VALUE (TREE_VALUE (arg1));
+- if (numofregs)
++ arg1 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1));
++ arg2 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2));
++ if (arg1 && arg2)
++ {
++ int num1 = 0, num2 = 0;
++ if (TREE_VALUE (arg1) && TREE_CODE (TREE_VALUE (arg1)) == TREE_LIST)
++ {
++ tree numofregs = TREE_VALUE (TREE_VALUE (arg1));
++ if (numofregs)
+ num1 = TREE_INT_CST_LOW (numofregs);
+- }
+- if (TREE_VALUE (arg2) && TREE_CODE (TREE_VALUE (arg2)) == TREE_LIST)
+- {
+- tree numofregs = TREE_VALUE (TREE_VALUE (arg2));
+- if (numofregs)
++ }
++ if (TREE_VALUE (arg2) && TREE_CODE (TREE_VALUE (arg2)) == TREE_LIST)
++ {
++ tree numofregs = TREE_VALUE (TREE_VALUE (arg2));
++ if (numofregs)
+ num2 = TREE_INT_CST_LOW (numofregs);
+- }
+- if (num1 != num2)
++ }
++ if (num1 != num2)
+ return 0; /* Different numbers, or no number in one type. */
+- }
+- }
++ }
++ }
+ #ifdef TARGET_AMIGAOS
+ return amigaos_comp_type_attributes(type1, type2);
+ #else
+- return 1;
++ return 1;
+ #endif
+-}
++ }
+ #endif
+
+ /* end-GG-local */
+
+-
+ /* Handle a "regparm", "stkparm" attribute;
+ arguments as in struct attribute_spec.handler. */
+ tree
+-amigaos_handle_type_attribute (tree *node, tree name, tree args,
+- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
++amigaos_handle_type_attribute (tree *node, tree name, tree args, int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+ {
+ tree nnn = *node;
+- do { // while (0);
+- DPRINTF(("%p with treecode %d\n", node, TREE_CODE(nnn)));
+- if (TREE_CODE (nnn) == FUNCTION_DECL || TREE_CODE (nnn) == FUNCTION_TYPE
+- || TREE_CODE (nnn) == METHOD_TYPE)
+- {
+- /* 'regparm' accepts one optional argument - number of registers in
+- single class that should be used to pass arguments. */
+- if (is_attribute_p ("regparm", name))
++ do
++ { // while (0);
++ DPRINTF(("%p with treecode %d\n", node, TREE_CODE(nnn)));
++ if (TREE_CODE (nnn) == FUNCTION_DECL || TREE_CODE (nnn) == FUNCTION_TYPE || TREE_CODE (nnn) == METHOD_TYPE)
+ {
+- DPRINTF(("regparm found\n"));
+-
+- if (lookup_attribute ("stkparm", TYPE_ATTRIBUTES(nnn)))
+- {
+- error ("`regparm' and `stkparm' are mutually exclusive");
+- break;
+- }
+- if (args && TREE_CODE (args) == TREE_LIST)
++ /* 'regparm' accepts one optional argument - number of registers in
++ single class that should be used to pass arguments. */
++ if (is_attribute_p ("regparm", name))
+ {
+- tree val = TREE_VALUE(args);
+- DPRINTF(("regparm with val: %d\n", TREE_CODE(val)));
+- if (TREE_CODE (val) == INTEGER_CST)
++ DPRINTF(("regparm found\n"));
++
++ if (lookup_attribute ("stkparm", TYPE_ATTRIBUTES(nnn)))
++ {
++ error ("`regparm' and `stkparm' are mutually exclusive");
++ break;
++ }
++ if (args && TREE_CODE (args) == TREE_LIST)
+ {
+- int no = TREE_INT_CST_LOW(val);
+- if (no < 0 || no > AMIGAOS_MAX_REGPARM)
++ tree val = TREE_VALUE(args);
++ DPRINTF(("regparm with val: %d\n", TREE_CODE(val)));
++ if (TREE_CODE (val) == INTEGER_CST)
+ {
+- error ("`regparm' attribute: value %d not in [0 - %d]",
+- no,
+- AMIGAOS_MAX_REGPARM);
++ int no = TREE_INT_CST_LOW(val);
++ if (no < 0 || no > AMIGAOS_MAX_REGPARM)
++ {
++ error ("`regparm' attribute: value %d not in [0 - %d]", no,
++ AMIGAOS_MAX_REGPARM);
++ break;
++ }
++ }
++ else
++ {
++ error ("invalid argument(s) to `regparm' attribute");
+ break;
+ }
+ }
+- else
++ }
++ else if (is_attribute_p ("stkparm", name))
++ {
++ if (lookup_attribute ("regparm", TYPE_ATTRIBUTES(nnn)))
+ {
+- error ("invalid argument(s) to `regparm' attribute");
++ error ("`regparm' and `stkparm' are mutually exclusive");
+ break;
+ }
+ }
+- }
+- else if (is_attribute_p ("stkparm", name))
+- {
+- if (lookup_attribute ("regparm", TYPE_ATTRIBUTES(nnn)))
++ else if (is_attribute_p ("stackext", name))
+ {
+- error ("`regparm' and `stkparm' are mutually exclusive");
+- break;
++ if (lookup_attribute ("interrupt", TYPE_ATTRIBUTES(nnn)))
++ {
++ error ("`stackext' and `interrupt' are mutually exclusive");
++ break;
++ }
+ }
+- }
+- else if (is_attribute_p ("stackext", name))
+- {
+- if (lookup_attribute ("interrupt", TYPE_ATTRIBUTES(nnn)))
++ else if (is_attribute_p ("saveds", name))
+ {
+- error ("`stackext' and `interrupt' are mutually exclusive");
+- break;
+ }
+ }
+- else if (is_attribute_p ("saveds", name))
++ else
+ {
++ warning (OPT_Wattributes, "`%s' attribute only applies to functions", IDENTIFIER_POINTER(name));
+ }
++ return NULL_TREE ;
+ }
+- else
+- {
+- warning (OPT_Wattributes, "`%s' attribute only applies to functions",
+- IDENTIFIER_POINTER(name));
+- }
+- return NULL_TREE;
+- } while (0);
++ while (0);
+ // error case
+ *no_add_attrs = true;
+- return NULL_TREE;
++ return NULL_TREE ;
+ }
+
+-
+ extern bool
+ m68k_rtx_costs (rtx, machine_mode, int, int, int *, bool);
+
+ bool
+-amigaos_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno,
+- int *total, bool speed)
++amigaos_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno, int *total, bool speed)
+ {
+ // DPRINTF(("outer: %d, opno: %d", outer_code, opno));
+ bool r = m68k_rtx_costs (x, mode, outer_code, opno, total, speed);
+@@ -790,13 +782,12 @@ amigaos_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno,
+ return r;
+ }
+
+-
+ /* Output assembly to switch to section NAME with attribute FLAGS. */
+
+ extern void
+ amiga_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_UNUSED)
+ {
+- if (0 == strncmp(".text", name, 5))
++ if (0 == strncmp (".text", name, 5))
+ name = ".text";
+ fprintf (asm_out_file, "\t%s\n", name);
+ }
+@@ -806,7 +797,8 @@ amiga_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_U
+ /**
+ * Does x reference the pic_reg and is const or plus?
+ */
+-int amiga_is_const_pic_ref(const_rtx x)
++int
++amiga_is_const_pic_ref (const_rtx x)
+ {
+ const_rtx y = x;
+ if (flag_pic < 3)
+@@ -816,19 +808,18 @@ int amiga_is_const_pic_ref(const_rtx x)
+ return (x != y && REG_P(y) && REGNO(y) == PIC_REG);
+ }
+
+-
+ /* Does operand (which is a symbolic_operand) live in text space? If
+- so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true.
++ so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true.
+
+- This function is used in base relative code generation. */
++ This function is used in base relative code generation. */
+
+ int
+ read_only_operand (rtx operand)
+ {
+ if (GET_CODE (operand) == CONST)
+- operand = XEXP (XEXP (operand, 0), 0);
++ operand = XEXP(XEXP (operand, 0), 0);
+ if (GET_CODE (operand) == SYMBOL_REF)
+- return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand);
++ return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P(operand);
+ return 1;
+ }
+
+
+From cbc99060c9a11080a62913d87030ad33ca15ae66 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 24 Apr 2017 23:55:30 +0200
+Subject: [PATCH 088/303] @B fix handling of jumps/labels in opt_reg_rename
+
+---
+ gcc/bbb-opts.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 97 insertions(+), 14 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index d0288f254f9c..db99815fee58 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -212,7 +212,6 @@ struct insn_info
+ _use &= ~o._def;
+ _use |= o._use;
+ _def = 0;
+- _hard &= ~_use;
+ }
+
+ inline bool
+@@ -339,6 +338,9 @@ copy_reg (rtx reg, int newregno)
+ static void
+ temp_reg_rename (std::vector<std::pair<rtx *, rtx> > & loc, rtx x, unsigned oldregno, unsigned newregno)
+ {
++ if (!x)
++ return;
++
+ RTX_CODE code = GET_CODE(x);
+
+ const char *fmt = GET_RTX_FORMAT(code);
+@@ -542,6 +544,7 @@ update_insn_infos (void)
+ if (pass && infos[pos].contains (ii))
+ break;
+
++ ii._hard = 0;
+ ii |= infos[pos];
+
+ if (LABEL_P(insn))
+@@ -646,7 +649,7 @@ update_insn_infos (void)
+ use.scan (pattern);
+ if (single_set (insn) == 0)
+ use._hard = use._use | use._def;
+-
++ else
+ /* if not cc0 defined check for mod. */
+ if (!use.is_def (FIRST_PSEUDO_REGISTER))
+ {
+@@ -684,6 +687,34 @@ bit2regno (unsigned bit)
+ return regno;
+ }
+
++static unsigned
++find_start (std::set<unsigned> & found, unsigned start, unsigned rename_regno)
++{
++ /* search the start. */
++ while (start < 0)
++ {
++ unsigned startm1 = start - 1;
++
++ /* already searched. */
++ if (found.find (startm1) != found.end ())
++ break;
++
++ /* do not run over RETURNS */
++ rtx_insn * before = insns[startm1];
++ if (JUMP_P(before) && ANY_RETURN_P(PATTERN (before)))
++ break;
++
++ start = startm1;
++
++ /* found the definition without use. */
++ insn_info & jj = infos[start];
++ if (jj.is_def (rename_regno) && !jj.is_use (rename_regno))
++ break;
++
++ }
++ return start;
++}
++
+ /*
+ * Always prefer lower register numbers within the class.
+ */
+@@ -696,10 +727,12 @@ opt_reg_rename (void)
+ insn_info & ii = infos[index];
+
+ /* do not rename if register is hard or used in same statement. */
+- const unsigned toRename = ii._def & ~ii._hard & ~ii._use;
+- if (!toRename)
++ const unsigned rename_regbit = ii._def & ~ii._hard & ~ii._use;
++ if (!rename_regbit)
+ continue;
+
++ const unsigned rename_regno = bit2regno (rename_regbit);
++
+ /* get the mask for free registers. */
+ unsigned mask = ii.get_free_mask ();
+ if (!mask)
+@@ -717,11 +750,36 @@ opt_reg_rename (void)
+ unsigned pos = todo[todo.size () - 1];
+ todo.pop_back ();
+
++ /* already searched. */
+ if (found.find (pos) != found.end ())
+ continue;
+
+- if (LABEL_P(insns[pos]))
++ rtx_insn * insn = insns[pos];
++ if (LABEL_P(insn))
+ {
++ found.insert (pos);
++
++ /* for each jump to this label:
++ * check if the reg was used at that jump.
++ * if used, find def
++ */
++ for (std::vector<rtx_insn *>::iterator i = jumps.begin (); i != jumps.end (); ++i)
++ {
++ if (JUMP_LABEL(*i) == insn)
++ {
++ std::map<rtx_insn *, unsigned>::iterator j = insn2index.find (*i);
++ if (j == insn2index.end ())
++ continue;
++
++ unsigned start = j->second;
++ if (!infos[start].is_use (rename_regno))
++ continue;
++
++ start = find_start (found, start, rename_regno);
++ todo.push_back (start);
++ }
++ }
++
+ if (pos + 1 < insns.size ())
+ todo.push_back (pos + 1);
+ continue;
+@@ -730,18 +788,18 @@ opt_reg_rename (void)
+ insn_info & jj = infos[pos];
+
+ /* marked as hard reg -> invalid rename */
+- if (jj._hard & toRename)
++ if (jj._hard & rename_regbit)
+ mask = 0;
+
+ /* defined again -> invalid rename */
+- if ((jj._def & toRename) && !(jj._use & toRename))
++ if ((jj._def & rename_regbit) && !(jj._use & rename_regbit))
+ mask = 0;
+
+ if (!mask)
+ break;
+
+ /* not used. */
+- if (!(jj._use & toRename))
++ if (!(jj._use & rename_regbit))
+ continue;
+
+ /* update free regs. */
+@@ -753,17 +811,41 @@ opt_reg_rename (void)
+ found.insert (pos);
+
+ /* follow jump and/or next insn. */
+- rtx_insn * insn = insns[pos];
+ if (JUMP_P(insn))
+ {
+ std::map<rtx_insn *, unsigned>::iterator j = insn2index.find ((rtx_insn *) JUMP_LABEL(insn));
+- if (j != insn2index.end ())
+- todo.push_back (j->second);
++ if (j == insn2index.end ())
++ {
++ /* whoops - label not found. */
++ todo.clear ();
++ mask = 0;
++ break;
++ }
+
++ unsigned label_index = j->second;
++ if (found.find (label_index) == found.end ())
++ {
++ /* if the rename_reg is used in the insn before.
++ * search the start.
++ */
++ if (label_index > 0)
++ {
++ insn_info & bb = infos[label_index - 1];
++ if (bb.is_use (rename_regbit))
++ {
++ unsigned start = find_start (found, label_index - 1, rename_regno);
++ todo.push_back (start);
++ }
++ }
++ todo.push_back (label_index);
++ }
+ rtx jmppattern = PATTERN (insn);
+ if (GET_CODE(jmppattern) == PARALLEL)
+ {
+- return 0; /* can't handle yet. Abort renaming. */
++ /* can't handle yet. Abort renaming. */
++ todo.clear ();
++ mask = 0;
++ break;
+ }
+
+ rtx jmpsrc = XEXP(jmppattern, 1);
+@@ -777,7 +859,7 @@ opt_reg_rename (void)
+
+ if (mask)
+ {
+- int oldregno = bit2regno (toRename);
++ int oldregno = bit2regno (rename_regbit);
+ int newregno = bit2regno (mask);
+
+ /* check the renamed insns. */
+@@ -812,7 +894,8 @@ opt_reg_rename (void)
+ if (!ok)
+ continue;
+
+- log ("opt_reg_rename %s -> %s (%d locs)\n", reg_names[oldregno], reg_names[newregno], patch.size ());
++ log ("opt_reg_rename %s -> %s (%d locs, start at %d)\n", reg_names[oldregno], reg_names[newregno],
++ patch.size (), index);
+
+ /* apply all changes. */
+ for (std::vector<std::pair<rtx *, rtx> >::iterator j = patch.begin (); j != patch.end (); ++j)
+
+From ee7031d5d1442ca1e933b3cb029f91ba1534354d Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 25 Apr 2017 11:30:06 +0200
+Subject: [PATCH 089/303] @B fix regrename...
+
+---
+ gcc/bbb-opts.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index db99815fee58..3e6c316149b0 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -691,7 +691,7 @@ static unsigned
+ find_start (std::set<unsigned> & found, unsigned start, unsigned rename_regno)
+ {
+ /* search the start. */
+- while (start < 0)
++ while (start > 0)
+ {
+ unsigned startm1 = start - 1;
+
+
+From e550db50f02dfa9bcfdf533e664ab032fca2a235 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 25 Apr 2017 12:42:11 +0200
+Subject: [PATCH 090/303] @R add target 'amigaosvasm' from
+ https://github.com/alpine9000/gcc
+
+---
+ config.sub | 6 ++--
+ gcc/config.gcc | 10 ++++++
+ gcc/config/m68k/amigaos.c | 19 ++++++++++-
+ gcc/config/m68k/m68k.c | 17 +++++++++-
+ gcc/config/m68k/m68k.h | 78 +++++++++++++++++++++++++++++++++++++++++--
+ gcc/config/m68k/m68kamigaos.h | 66 ++++++++++++++++++++++++++++++++++--
+ 6 files changed, 185 insertions(+), 11 deletions(-)
+
+diff --git a/config.sub b/config.sub
+index 41146e11c6c9..35247fe0c474 100755
+--- config.sub
++++ config.sub
+@@ -2,7 +2,7 @@
+ # Configuration validation subroutine script.
+ # Copyright 1992-2016 Free Software Foundation, Inc.
+
+-timestamp='2016-01-01'
++timestamp='2017-04-21'
+
+ # This file is free software; you can redistribute it and/or modify it
+ # under the terms of the GNU General Public License as published by
+@@ -500,7 +500,7 @@ case $basic_machine in
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+- amigaos | amigados)
++ amigaos | amigaosvasm | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+@@ -1380,7 +1380,7 @@ case $os in
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* | -aros* | -cloudabi* | -sortix* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+- | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
++ | -clix* | -riscos* | -uniplus* | -iris* | -rt* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+ | -bitrig* | -openbsd* | -solidbsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+diff --git a/gcc/config.gcc b/gcc/config.gcc
+index 762594c073ae..0beee32c863c 100644
+--- gcc/config.gcc
++++ gcc/config.gcc
+@@ -1936,6 +1936,16 @@ m68k-*-elf* | fido-*-elf*)
+ ;;
+ esac
+ ;;
++m68k*-*-amigaosvasm*)
++ default_m68k_cpu=68000
++ tm_file="${tm_file} dbx.h newlib-stdint.h m68k/m68kamigaos.h"
++ tm_defines="${tm_defines} MOTOROLA=1 TARGET_AMIGAOS TARGET_AMIGAOS_VASM TARGET_CPU_DEFAULT=0"
++ tmake_file="m68k/t-floatlib m68k/t-m68kbare m68k/t-amigaos"
++ tm_p_file="${tm_p_file} m68k/amigaos-protos.h"
++ extra_objs=amigaos.o
++ extra_options="${extra_options} m68k/amigaos.opt"
++ gnu_ld=yes
++ ;;
+ m68k*-*-amigaos*)
+ default_m68k_cpu=68000
+ tm_file="${tm_file} dbx.h newlib-stdint.h m68k/m68kamigaos.h"
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index c93188a3e90d..27831df2d543 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -50,6 +50,7 @@
+
+ //int amiga_declare_object;
+
++
+ #if 0
+ static int amigaos_put_in_text (tree);
+ static rtx gen_stack_management_call (rtx, rtx, const char *);
+@@ -783,7 +784,7 @@ amigaos_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno, int *tota
+ }
+
+ /* Output assembly to switch to section NAME with attribute FLAGS. */
+-
++#ifndef TARGET_AMIGAOS_VASM
+ extern void
+ amiga_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_UNUSED)
+ {
+@@ -791,6 +792,22 @@ amiga_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_U
+ name = ".text";
+ fprintf (asm_out_file, "\t%s\n", name);
+ }
++#else
++extern void
++amiga_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_UNUSED)
++{
++ if (0 == strncmp(".text", name, 5))
++ name = ".text";
++
++ if (0 == strncmp("section ", name, 8)) {
++// fprintf (asm_out_file, "\t.section\t%s\n", name);
++ fprintf (asm_out_file, "\t%s\n", name);
++ } else {
++ fprintf (asm_out_file, "\tsection %s\n", name);
++ }
++}
++#endif
++
+
+ /* Baserel support. */
+
+diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
+index 3fabe00a678a..8a40cbc2ab1f 100644
+--- gcc/config/m68k/m68k.c
++++ gcc/config/m68k/m68k.c
+@@ -191,7 +191,11 @@ static void m68k_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
+
+ #if INT_OP_GROUP == INT_OP_DOT_WORD
+ #undef TARGET_ASM_ALIGNED_HI_OP
++#ifndef TARGET_AMIGAOS_VASM
+ #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
++#else
++#define TARGET_ASM_ALIGNED_HI_OP "\tdc.w\t"
++#endif
+ #endif
+
+ #if INT_OP_GROUP == INT_OP_NO_DOT
+@@ -595,8 +599,11 @@ m68k_option_override (void)
+ if (!flag_pic || flag_pic > 2)
+ {
+ m68k_symbolic_call_var = M68K_SYMBOLIC_CALL_JSR;
+-
++#ifndef TARGET_AMIGAOS_VASM
+ m68k_symbolic_jump = "jra %a0";
++#else
++ m68k_symbolic_jump = "jmp %a0";
++#endif
+ }
+ else if (TARGET_ID_SHARED_LIBRARY)
+ /* All addresses must be loaded from the GOT. */
+@@ -1831,13 +1838,21 @@ output_btst (rtx *operands, rtx countop, rtx dataop, rtx_insn *insn, int signpos
+ && next_insn_tests_no_inequality (insn))
+ {
+ cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N | CC_NO_OVERFLOW;
++#ifndef TARGET_AMIGAOS_VASM
+ return "move%.w %1,%%ccr";
++#else
++ return "move%.w %1,ccr";
++#endif
+ }
+ if (count == 2 && DATA_REG_P (operands[1])
+ && next_insn_tests_no_inequality (insn))
+ {
+ cc_status.flags = CC_NOT_NEGATIVE | CC_INVERTED | CC_NO_OVERFLOW;
++#ifndef TARGET_AMIGAOS_VASM
+ return "move%.w %1,%%ccr";
++#else
++ return "move%.w %1,ccr";
++#endif
+ }
+ /* count == 1 followed by bvc/bvs and
+ count == 0 followed by bcc/bcs are also possible, but need
+diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h
+index 5142adf24e4d..200f07ef63a4 100644
+--- gcc/config/m68k/m68k.h
++++ gcc/config/m68k/m68k.h
+@@ -204,7 +204,11 @@ along with GCC; see the file COPYING3. If not see
+ #define INT_OP_DC 3 /* dc.b, dc.w, dc.l */
+
+ /* Set the default. */
++#ifndef TARGET_AMIGAOS_VASM
+ #define INT_OP_GROUP INT_OP_DOT_WORD
++#else
++#define INT_OP_GROUP INT_OP_DC
++#endif
+
+ /* Bit values used by m68k-devices.def to identify processor capabilities. */
+ #define FL_BITFIELD (1 << 0) /* Support bitfield instructions. */
+@@ -729,9 +733,49 @@ do { if (cc_prev_status.flags & CC_IN_68881) \
+ if (cc_prev_status.flags & CC_NO_OVERFLOW) \
+ return NO_OV; \
+ return NORMAL; } while (0)
++
++#ifdef TARGET_AMIGAOS_VASM
++#define ASM_OUTPUT_ASCII(MYFILE, MYSTRING, MYLENGTH) \
++ do { \
++ FILE *_hide_asm_out_file = (MYFILE); \
++ const unsigned char *_hide_p = (const unsigned char *) (MYSTRING); \
++ int _hide_thissize = (MYLENGTH); \
++ { \
++ FILE *asm_out_file = _hide_asm_out_file; \
++ const unsigned char *p = _hide_p; \
++ int thissize = _hide_thissize; \
++ int i; \
++ fprintf (asm_out_file, "\tdc.b \""); \
++ \
++ for (i = 0; i < thissize; i++) \
++ { \
++ int c = p[i]; \
++ if (c == '\"' || c == '\\') \
++ putc ('\\', asm_out_file); \
++ if (ISPRINT (c)) \
++ putc (c, asm_out_file); \
++ else \
++ { \
++ fprintf (asm_out_file, "\\%o", c); \
++ /* After an octal-escape, if a digit follows, \
++ terminate one string constant and start another. \
++ The VAX assembler fails to stop reading the escape \
++ after three digits, so this is the only way we \
++ can get it to parse the data properly. */ \
++ if (i < thissize - 1 && ISDIGIT (p[i + 1])) \
++ fprintf (asm_out_file, "\"\n\tdc.b \""); \
++ } \
++ } \
++ fprintf (asm_out_file, "\"\n"); \
++ } \
++ } \
++ while (0)
++#endif
+
++
+ /* Control the assembler format that we output. */
+
++#ifndef TARGET_AMIGAOS_VASM
+ #define ASM_APP_ON "#APP\n"
+ #define ASM_APP_OFF "#NO_APP\n"
+ #define TEXT_SECTION_ASM_OP "\t.text"
+@@ -741,6 +785,17 @@ do { if (cc_prev_status.flags & CC_IN_68881) \
+ #define LOCAL_LABEL_PREFIX ""
+ #define USER_LABEL_PREFIX "_"
+ #define IMMEDIATE_PREFIX "#"
++#else
++#define ASM_APP_ON ""
++#define ASM_APP_OFF ""
++#define TEXT_SECTION_ASM_OP "\tsection .text"
++#define DATA_SECTION_ASM_OP "\tsection .data"
++#define GLOBAL_ASM_OP "\txdef\t"
++#define REGISTER_PREFIX ""
++#define LOCAL_LABEL_PREFIX "_."
++#define USER_LABEL_PREFIX "_"
++#define IMMEDIATE_PREFIX "#"
++#endif
+
+ #define REGISTER_NAMES \
+ {REGISTER_PREFIX"d0", REGISTER_PREFIX"d1", REGISTER_PREFIX"d2", \
+@@ -860,11 +915,17 @@ do { if (cc_prev_status.flags & CC_IN_68881) \
+
+ /* The m68k does not use absolute case-vectors, but we must define this macro
+ anyway. */
+-#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
++#ifndef TARGET_AMIGAOS_VASM
++#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ asm_fprintf (FILE, "\t.long %LL%d\n", VALUE)
+-
+-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
++#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
+ asm_fprintf (FILE, "\t.word %LL%d-%LL%d\n", VALUE, REL)
++#else
++#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
++ asm_fprintf (FILE, "\tdc.l %LL%d\n", VALUE)
++#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
++ asm_fprintf (FILE, "\tdc.w %LL%d-%LL%d\n", VALUE, REL)
++#endif
+
+ /* We don't have a way to align to more than a two-byte boundary, so do the
+ best we can and don't complain. */
+@@ -874,13 +935,24 @@ do { if (cc_prev_status.flags & CC_IN_68881) \
+
+ #ifdef HAVE_GAS_BALIGN_AND_P2ALIGN
+ /* Use "move.l %a4,%a4" to advance within code. */
++#ifndef TARGET_AMIGAOS_VASM
+ #define ASM_OUTPUT_ALIGN_WITH_NOP(FILE,LOG) \
+ if ((LOG) > 0) \
+ fprintf ((FILE), "\t.balignw %u,0x284c\n", 1 << (LOG));
+ #endif
++#else
++#define ASM_OUTPUT_ALIGN_WITH_NOP(FILE,LOG) \
++ if ((LOG) > 0) \
++ fprintf ((FILE), "\tcnop 0,%u\n", 1 << (LOG));
++#endif
+
++#ifndef TARGET_AMIGAOS_VASM
+ #define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\t.skip %u\n", (int)(SIZE))
++#else
++#define ASM_OUTPUT_SKIP(FILE,SIZE) \
++ fprintf (FILE, "\tds.b %u\n", (int)(SIZE))
++#endif
+
+ #define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+ ( fputs (".comm ", (FILE)), \
+diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h
+index 20e0b66face2..3ca2cd666e7c 100644
+--- gcc/config/m68k/m68kamigaos.h
++++ gcc/config/m68k/m68kamigaos.h
+@@ -61,7 +61,11 @@ along with GCC; see the file COPYING3. If not see
+ These labels will not appear in the symbol table. */
+
+ #undef LOCAL_LABEL_PREFIX
++#ifndef TARGET_AMIGAOS_VASM
+ #define LOCAL_LABEL_PREFIX "."
++#else
++#define LOCAL_LABEL_PREFIX "_."
++#endif
+
+ /* The prefix to add to user-visible assembler symbols. */
+
+@@ -71,24 +75,43 @@ along with GCC; see the file COPYING3. If not see
+ /* config/m68k.md has an explicit reference to the program counter,
+ prefix this by the register prefix. */
+
++#ifndef TARGET_AMIGAOS_VASM
+ #define ASM_RETURN_CASE_JUMP \
+ do { \
+ return "jmp %%pc@(2,%0:w)"; \
+ } while (0)
++#else
++#define ASM_RETURN_CASE_JUMP \
++ do { \
++ return "jmp (2,pc,%0.w)"; \
++ } while (0)
++#endif
+
+ /* This is how to output an assembler line that says to advance the
+ location counter to a multiple of 2**LOG bytes. */
+
++#ifndef TARGET_AMIGAOS_VASM
+ #ifndef ALIGN_ASM_OP
+ #define ALIGN_ASM_OP "\t.align\t"
+ #endif
++#else
++#define ALIGN_ASM_OP "\talign\t"
++#endif
+
+ #undef ASM_OUTPUT_ALIGN
++#ifndef TARGET_AMIGAOS_VASM
+ #define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ do { \
+ if ((LOG) > 0) \
+ fprintf ((FILE), "%s%u\n", ALIGN_ASM_OP, 1 << (LOG)); \
+ } while (0)
++#else
++#define ASM_OUTPUT_ALIGN(FILE,LOG) \
++do { \
++ if ((LOG) > 0) \
++ fprintf ((FILE), "%s%u\n", ALIGN_ASM_OP, (LOG)); \
++} while (0)
++#endif
+
+ #if 0
+ extern int amiga_declare_object;
+@@ -126,7 +149,11 @@ amiga_declare_object = 0
+ #undef M68K_STATIC_CHAIN_REG_NAME
+ #define M68K_STATIC_CHAIN_REG_NAME REGISTER_PREFIX "a1"
+
++#ifndef TARGET_AMIGAOS_VASM
++#define ASM_COMMENT_START "|"
++#else
+ #define ASM_COMMENT_START "|"
++#endif
+
+ /* Define how the m68k registers should be numbered for Dwarf output.
+ The numbering provided here should be compatible with the native
+@@ -147,15 +174,34 @@ amiga_declare_object = 0
+
+ #undef ASM_OUTPUT_COMMON
+ #undef ASM_OUTPUT_LOCAL
+-#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
++#ifndef TARGET_AMIGAOS_VASM
++#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+ ( fputs (".comm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (int)(SIZE)))
++#else
++#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
++ ( switch_to_section (bss_section), \
++ fputs ("|.comm\n\tcnop 0,4\n", (FILE)), \
++ assemble_name ((FILE), (NAME)), \
++ fprintf ((FILE), ":\n\tds.b %u\n", (int)(SIZE)), \
++ fputs ("\txdef ", (FILE)), \
++ assemble_name ((FILE), (NAME)), \
++ fprintf ((FILE), "\n"))
++#endif
+
++#ifndef TARGET_AMIGAOS_VASM
+ #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+ ( fputs (".lcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (int)(SIZE)))
++#else
++#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
++( switch_to_section (bss_section), \
++ fputs ("|.lcomm\n\tcnop 0,4\n", (FILE)), \
++ assemble_name ((FILE), (NAME)), \
++ fprintf ((FILE), ":\n\tds.b %u\n", (int)(SIZE)))
++#endif
+
+ /* Currently, JUMP_TABLES_IN_TEXT_SECTION must be defined in order to
+ keep switch tables in the text section. */
+@@ -169,9 +215,13 @@ amiga_declare_object = 0
+ fprintf ((FILE), "%s&%d\n", SWBEG_ASM_OP, XVECLEN (PATTERN (TABLE), 1));
+ /* end of stuff from m68kv4.h */
+
++#ifndef TARGET_AMIGAOS_VASM
+ #ifndef BSS_SECTION_ASM_OP
+ #define BSS_SECTION_ASM_OP "\t.bss"
+ #endif
++#else
++#define BSS_SECTION_ASM_OP "\tsection\tbss"
++#endif
+
+ #ifndef ASM_OUTPUT_ALIGNED_BSS
+ #define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
+@@ -294,8 +344,13 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ /* Various -m flags require special flags to the assembler. */
+
+ #undef ASM_SPEC
++#ifndef TARGET_AMIGAOS_VASM
++#define ASM_SPEC \
++ "%(asm_cpu) %(asm_cpu_default) %{msmall-code:-sc}"
++#else
+ #define ASM_SPEC \
+- "%(asm_cpu) %(asm_cpu_default) %{msmall-code:-sc}"
++ "-gas -esc -ldots -Fhunk -quiet %(asm_cpu) %(asm_cpu_default) %{msmall-code:-sc}"
++#endif
+
+ #undef ASM_CPU_SPEC
+ #define ASM_CPU_SPEC \
+@@ -305,8 +360,13 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ "%{m68040} " \
+ "%{m68060}"
+
++#ifndef TARGET_AMIGAOS_VASM
+ #define ASM_CPU_DEFAULT_SPEC \
+- "%{!m680*:%{!mc680*:-m68040}}"
++ "%{!m680*:%{!mc680*:-m68040}}"
++#else
++#define ASM_CPU_DEFAULT_SPEC \
++ "%{!m680*:%{!mc680*:-m68000}}"
++#endif
+
+ /* Choose the right startup file, depending on whether we use base relative
+ code, base relative code with automatic relocation (-resident), their
+
+From c48a0f72eefe8e3a45b24184fc75e5a93eaabfc2 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 25 Apr 2017 19:37:45 +0200
+Subject: [PATCH 091/303] @B renaming is better again, test cases stil ok
+
+---
+ gcc/bbb-opts.c | 163 +++++++++++++++++++++++++++++----------------------------
+ 1 file changed, 82 insertions(+), 81 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 3e6c316149b0..407e2f74fd9f 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -738,123 +738,124 @@ opt_reg_rename (void)
+ if (!mask)
+ continue;
+
+- std::set<unsigned> found;
++ /* first = pos to start, second indicates to treat def as use. */
+ std::vector<unsigned> todo;
++ std::set<unsigned> found;
+ if (index + 1 < insns.size ())
+ todo.push_back (index + 1);
+
++// /* trigger jump checking */
++// if (index > 0 && LABEL_P(insns[index - 1]))
++// todo.push_back (std::make_pair(index - 1, 0));
++
+ found.insert (index);
+ /* a register was defined, follow all branches. */
+- while (todo.size ())
++ while (mask && todo.size ())
+ {
+- unsigned pos = todo[todo.size () - 1];
++ unsigned runpos = todo[todo.size () - 1];
+ todo.pop_back ();
+
+- /* already searched. */
+- if (found.find (pos) != found.end ())
+- continue;
+-
+- rtx_insn * insn = insns[pos];
+- if (LABEL_P(insn))
++ for (unsigned pos = runpos; mask && pos < insns.size (); ++pos)
+ {
+- found.insert (pos);
++ /* already searched. */
++ if (found.find (pos) != found.end ())
++ break;
+
+- /* for each jump to this label:
+- * check if the reg was used at that jump.
+- * if used, find def
+- */
+- for (std::vector<rtx_insn *>::iterator i = jumps.begin (); i != jumps.end (); ++i)
++ rtx_insn * insn = insns[pos];
++ if (LABEL_P(insn))
+ {
+- if (JUMP_LABEL(*i) == insn)
++ found.insert (pos);
++
++ /* for each jump to this label:
++ * check if the reg was used at that jump.
++ * if used, find def
++ */
++ for (std::vector<rtx_insn *>::iterator i = jumps.begin (); i != jumps.end (); ++i)
+ {
+- std::map<rtx_insn *, unsigned>::iterator j = insn2index.find (*i);
+- if (j == insn2index.end ())
+- continue;
++ if (JUMP_LABEL(*i) == insn)
++ {
++ std::map<rtx_insn *, unsigned>::iterator j = insn2index.find (*i);
++ if (j == insn2index.end ())
++ continue;
+
+- unsigned start = j->second;
+- if (!infos[start].is_use (rename_regno))
+- continue;
++ unsigned start = j->second;
++ if (!infos[start].is_use (rename_regno))
++ continue;
+
+- start = find_start (found, start, rename_regno);
+- todo.push_back (start);
++ start = find_start (found, start, rename_regno);
++ todo.push_back (start);
++ }
+ }
++ continue;
+ }
+
+- if (pos + 1 < insns.size ())
+- todo.push_back (pos + 1);
+- continue;
+- }
++ insn_info & jj = infos[pos];
+
+- insn_info & jj = infos[pos];
++ /* marked as hard reg -> invalid rename */
++ if (jj._use & jj._hard & rename_regbit)
++ mask = 0;
+
+- /* marked as hard reg -> invalid rename */
+- if (jj._hard & rename_regbit)
+- mask = 0;
++// /* defined again -> invalid rename */
++// if ((jj._def & rename_regbit) && !(jj._use & rename_regbit))
++// mask = 0;
+
+- /* defined again -> invalid rename */
+- if ((jj._def & rename_regbit) && !(jj._use & rename_regbit))
+- mask = 0;
+-
+- if (!mask)
+- break;
++ if (!mask)
++ break;
+
+- /* not used. */
+- if (!(jj._use & rename_regbit))
+- continue;
++ /* not used. and not a def */
++ if (pos == runpos && (jj._def & rename_regbit))
++ {
++ /* continue since this pos was added by start search. */
++ }
++ else if (!(jj._use & rename_regbit))
++ break;
+
+- /* update free regs. */
+- mask &= ~jj._use;
+- mask &= ~jj._def;
+- if (!mask)
+- break;
++ /* update free regs. */
++ mask &= ~jj._use;
++ mask &= ~jj._def;
++ if (!mask)
++ break;
+
+- found.insert (pos);
++ found.insert (pos);
+
+- /* follow jump and/or next insn. */
+- if (JUMP_P(insn))
+- {
+- std::map<rtx_insn *, unsigned>::iterator j = insn2index.find ((rtx_insn *) JUMP_LABEL(insn));
+- if (j == insn2index.end ())
++ /* follow jump and/or next insn. */
++ if (JUMP_P(insn))
+ {
+- /* whoops - label not found. */
+- todo.clear ();
+- mask = 0;
+- break;
+- }
++ std::map<rtx_insn *, unsigned>::iterator j = insn2index.find ((rtx_insn *) JUMP_LABEL(insn));
++ if (j == insn2index.end ())
++ {
++ /* whoops - label not found. */
++ mask = 0;
++ break;
++ }
+
+- unsigned label_index = j->second;
+- if (found.find (label_index) == found.end ())
+- {
+- /* if the rename_reg is used in the insn before.
+- * search the start.
+- */
+- if (label_index > 0)
++ unsigned label_index = j->second;
++ if (found.find (label_index) == found.end ())
+ {
+- insn_info & bb = infos[label_index - 1];
++ /* if the rename_reg is used in the insn before.
++ * search the start.
++ */
++ insn_info & bb = infos[label_index + 1];
+ if (bb.is_use (rename_regbit))
+ {
+ unsigned start = find_start (found, label_index - 1, rename_regno);
+ todo.push_back (start);
+ }
++ todo.push_back (label_index + 1);
++ }
++ rtx jmppattern = PATTERN (insn);
++ if (GET_CODE(jmppattern) == PARALLEL)
++ {
++ /* can't handle yet. Abort renaming. */
++ mask = 0;
++ break;
+ }
+- todo.push_back (label_index);
+- }
+- rtx jmppattern = PATTERN (insn);
+- if (GET_CODE(jmppattern) == PARALLEL)
+- {
+- /* can't handle yet. Abort renaming. */
+- todo.clear ();
+- mask = 0;
+- break;
+- }
+
+- rtx jmpsrc = XEXP(jmppattern, 1);
+- if (jmpsrc && GET_CODE(jmpsrc) == IF_THEN_ELSE)
+- if (pos + 1 < insns.size ())
+- todo.push_back (pos + 1);
++ rtx jmpsrc = XEXP(jmppattern, 1);
++ if (!jmpsrc || GET_CODE(jmpsrc) != IF_THEN_ELSE)
++ break;
++ }
+ }
+- else if (pos + 1 < insns.size ())
+- todo.push_back (pos + 1);
+ }
+
+ if (mask)
+
+From 50dc4c0949e49397d6c6de28207d34cbf137621c Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 26 Apr 2017 10:34:16 +0200
+Subject: [PATCH 092/303] @B fix backward search at labels
+
+---
+ gcc/bbb-opts.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 407e2f74fd9f..78eb0cc32f38 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -836,7 +836,7 @@ opt_reg_rename (void)
+ * search the start.
+ */
+ insn_info & bb = infos[label_index + 1];
+- if (bb.is_use (rename_regbit))
++ if (bb.is_use (rename_regno))
+ {
+ unsigned start = find_start (found, label_index - 1, rename_regno);
+ todo.push_back (start);
+
+From ec53abb40b3066d74243c566ea7528ac1bd0f150 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 26 Apr 2017 11:43:37 +0200
+Subject: [PATCH 093/303] @I no longer using df functions to determine reg use.
+ @B fixed propagate moves, @B fixed eliminate dead assignments
+
+---
+ gcc/bbb-opts.c | 278 +++++++++++++++++++++++++++++++--------------------------
+ 1 file changed, 149 insertions(+), 129 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 78eb0cc32f38..9d138063fb27 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -58,7 +58,6 @@
+ #include "backend.h"
+ #include "target.h"
+ #include "rtl.h"
+-#include "df.h"
+ #include "tm_p.h"
+ #include "insn-config.h"
+ #include "recog.h"
+@@ -242,6 +241,9 @@ struct insn_info
+ return true;
+ }
+
++ void
++ scan_call (rtx_insn *);
++
+ void
+ scan (rtx);
+
+@@ -267,6 +269,31 @@ struct insn_info
+ }
+ };
+
++void
++insn_info::scan_call (rtx_insn * insn)
++{
++ /* add mregparm registers. */
++ for (rtx link = CALL_INSN_FUNCTION_USAGE(insn); link; link = XEXP(link, 1))
++ {
++ rtx op, reg;
++
++ if (GET_CODE (op = XEXP (link, 0)) == USE && REG_P(reg = XEXP (op, 0)))
++ for (unsigned r = REGNO(reg); r <= END_REGNO (reg); ++r)
++ use (r);
++ }
++ /* also mark all registers as not renamable */
++ _hard = _use;
++
++ scan (PATTERN (insn));
++
++ /* mark scratch registers. */
++ def (0);
++ def (1);
++ def (8);
++ def (9);
++
++}
++
+ /* scan rtx for registers and set the corresponding flags. */
+ void
+ insn_info::scan (rtx x)
+@@ -478,8 +505,6 @@ update_insns ()
+ rtx_insn *insn, *next;
+ clear ();
+
+- // df_insn_rescan_all ();
+-
+ char inproepilogue = 1;
+ /* create a vector with relevant insn. */
+ for (insn = get_insns (); insn; insn = next)
+@@ -567,26 +592,7 @@ update_insn_infos (void)
+ if (CALL_P(insn))
+ {
+ insn_info use;
+-
+- /* add mregparm registers. */
+- for (rtx link = CALL_INSN_FUNCTION_USAGE(insn); link; link = XEXP(link, 1))
+- {
+- rtx op, reg;
+-
+- if (GET_CODE (op = XEXP (link, 0)) == USE && REG_P(reg = XEXP (op, 0)))
+- for (unsigned r = REGNO(reg); r <= END_REGNO (reg); ++r)
+- use.use (r);
+- }
+- /* also mark all registers as not renamable */
+- use._hard = use._use;
+-
+- use.scan (pattern);
+-
+- /* mark scratch registers. */
+- use.def (0);
+- use.def (1);
+- use.def (8);
+- use.def (9);
++ use.scan_call (insn);
+
+ infos[pos] = use | ii;
+ ii.updateWith (use);
+@@ -687,6 +693,27 @@ bit2regno (unsigned bit)
+ return regno;
+ }
+
++/* check if that register is touched between from and to, excluding from and to .*/
++static bool
++is_reg_touched_between (unsigned regno, int from, int to)
++{
++ for (int index = from + 1; index < to; ++index)
++ {
++ insn_info ii;
++ rtx_insn * insn = insns[index];
++ if (CALL_P(insn))
++ ii.scan_call (insn);
++ else
++ ii.scan (PATTERN (insn));
++ if (ii.is_use (regno) || ii.is_def (regno))
++ return true;
++ }
++ return false;
++}
++
++/*
++ * search backward and find the initial assignment for that regno.
++ */
+ static unsigned
+ find_start (std::set<unsigned> & found, unsigned start, unsigned rename_regno)
+ {
+@@ -1045,47 +1072,76 @@ opt_propagate_moves ()
+ if (rtx_equal_p (srci, dstj) && rtx_equal_p (srcj, dsti))
+ {
+ /* Ensure correct usage. */
+- if (!reg_used_between_p (srci, current_label, ii) && !reg_used_between_p (srci, ii, jj)
+- && !reg_used_between_p (srci, jj, insn) && !reg_used_between_p (dsti, current_label, ii)
+- && !reg_used_between_p (dsti, jj, insn))
++ if (is_reg_touched_between (REGNO(srci), current_label_index, *i) // label ... move src,x
++ || is_reg_touched_between (REGNO(srci), *i, *j) // move src,x ... move x,src
++ || is_reg_touched_between (REGNO(srci), *j, index) // move x,src ... jcc
++ || is_reg_touched_between (REGNO(dsti), *j, index) // label ... move src,x
++ || is_reg_touched_between (REGNO(dsti), *j, index) // move x,src ... jcc
++ )
++ {
++ ++j;
++ continue;
++ }
++
++ std::vector<int> fixups;
++
++ /* if there are jumps out of the loop,
++ * check if the modification occurs before the jump,
++ * and if, that it's a plus const.
++ */
++ if (jump_out.size ())
+ {
+- std::vector<int> fixups;
++ std::vector<rtx_insn *>::iterator label_iter = jump_out.begin ();
++ int fixup = 0;
+
+- /* if there are jumps out of the loop,
+- * check if the modification occurs before the jump,
+- * and if, that it's a plus const.
+- */
+- if (jump_out.size ())
++ for (unsigned k = *i + 1; k != *j; ++k)
+ {
+- std::vector<rtx_insn *>::iterator label_iter = jump_out.begin ();
+- int fixup = 0;
++ rtx_insn * check = insns[k];
++ if (JUMP_P(check))
++ {
++ fixups.push_back (fixup);
++ if (++label_iter == jump_out.end ())
++ break;
++ continue;
++ }
+
+- for (unsigned k = *i + 1; k != *j; ++k)
++ if (reg_overlap_mentioned_p (dsti, PATTERN (check)))
+ {
+- rtx_insn * check = insns[k];
+- if (JUMP_P(check))
++ /* right now only support auto_incs. */
++ rtx set = single_set (check);
++ rtx src = SET_SRC(set);
++ rtx dst = SET_DEST(set);
++
++ if (reg_overlap_mentioned_p (dsti, dst))
+ {
+- fixups.push_back (fixup);
+- if (++label_iter == jump_out.end ())
++ if (REG_P(dst))
++ break;
++ if (!MEM_P(dst))
++ break;
++
++ rtx x = XEXP(dst, 0);
++ if (GET_CODE(x) == REG)
++ fixup += 0; // direct use
++ else if (GET_CODE(x) == PRE_INC ||
++ GET_CODE(x) == POST_INC)
++ fixup -= GET_MODE_SIZE(GET_MODE(dst));
++ else if (GET_CODE(dst) == PRE_DEC ||
++ GET_CODE(dst) == POST_DEC)
++ fixup += GET_MODE_SIZE(GET_MODE(dst));
++ else
+ break;
+- continue;
+ }
+
+- if (reg_overlap_mentioned_p (dsti, PATTERN (check)))
++ if (reg_overlap_mentioned_p (dsti, src))
+ {
+- /* right now only support auto_incs. */
+- rtx set = single_set (check);
+- rtx src = SET_SRC(set);
+- rtx dst = SET_DEST(set);
+-
+- if (reg_overlap_mentioned_p (dsti, dst))
++ if (REG_P(src))
++ fixup += 0;
++ else
+ {
+- if (REG_P(dst))
+- break;
+- if (!MEM_P(dst))
++ if (!MEM_P(src))
+ break;
+
+- rtx x = XEXP(dst, 0);
++ rtx x = XEXP(src, 0);
+ if (GET_CODE(x) == REG)
+ fixup += 0; // direct use
+ else if (GET_CODE(x) == PRE_INC ||
+@@ -1097,91 +1153,64 @@ opt_propagate_moves ()
+ else
+ break;
+ }
+-
+- if (reg_overlap_mentioned_p (dsti, src))
+- {
+- if (REG_P(src))
+- fixup += 0;
+- else
+- {
+- if (!MEM_P(src))
+- break;
+-
+- rtx x = XEXP(src, 0);
+- if (GET_CODE(x) == REG)
+- fixup += 0; // direct use
+- else if (GET_CODE(x) == PRE_INC ||
+- GET_CODE(x) == POST_INC)
+- fixup -= GET_MODE_SIZE(GET_MODE(dst));
+- else if (GET_CODE(dst) == PRE_DEC ||
+- GET_CODE(dst) == POST_DEC)
+- fixup += GET_MODE_SIZE(GET_MODE(dst));
+- else
+- break;
+- }
+- }
+ }
+ }
+ }
++ }
+
+- /* got a fixup for all jump_outs? */
+- if (fixups.size () == jump_out.size ())
+- {
+- rtx_insn * before = insns[current_label_index - 1];
+- rtx_insn * after = insns[index + 1];
+- rtx bset = single_set (before);
++ /* got a fixup for all jump_outs? */
++ if (fixups.size () == jump_out.size ())
++ {
++ rtx_insn * before = insns[current_label_index - 1];
++ rtx_insn * after = insns[index + 1];
++ rtx bset = single_set (before);
+
+- log ("propagate_moves condition met, moving regs %s, %s\n",
+- reg_names[REGNO(srci)],
+- reg_names[REGNO(dsti)]);
++ log ("propagate_moves condition met, moving regs %s, %s\n",
++ reg_names[REGNO(srci)],
++ reg_names[REGNO(dsti)]);
+
+- /* Move in front of loop and mark as dead. */
+- rtx_insn * newii = make_insn_raw (PATTERN (ii));
+- SET_INSN_DELETED(ii);
++ /* Move in front of loop and mark as dead. */
++ rtx_insn * newii = make_insn_raw (PATTERN (ii));
++ SET_INSN_DELETED(ii);
+
+- /* Plus check if the reg was just loaded. */
+- if (bset)
++ /* Plus check if the reg was just loaded. */
++ if (bset)
++ {
++ rtx bdst = SET_DEST(bset);
++ if (REG_P(bdst) && REGNO(bdst) == REGNO(srci))
+ {
+- rtx bdst = SET_DEST(bset);
+- if (REG_P(bdst) && REGNO(bdst) == REGNO(srci))
+- {
+- SET_SRC(PATTERN(newii)) = SET_SRC(bset);
++ SET_SRC(PATTERN(newii)) = SET_SRC(bset);
+ // SET_INSN_DELETED(ii);
+- }
+ }
+- else
+- add_reg_note (newii, REG_DEAD, srci);
++ }
++ else
++ add_reg_note (newii, REG_DEAD, srci);
+
+- add_insn_after (newii, before, 0);
++ add_insn_after (newii, before, 0);
+
+- /* Move behind loop - into next BB. */
+- rtx_insn * newjj = make_insn_raw (PATTERN (jj));
+- add_insn_before (newjj, after, 0);
+- SET_INSN_DELETED(jj);
++ /* Move behind loop - into next BB. */
++ rtx_insn * newjj = make_insn_raw (PATTERN (jj));
++ add_insn_before (newjj, after, 0);
++ SET_INSN_DELETED(jj);
+
+- reg_reg.erase (j);
+- reg_reg.erase (i);
+- j = reg_reg.end ();
+- inc = false;
++ reg_reg.erase (j);
++ reg_reg.erase (i);
++ j = reg_reg.end ();
++ inc = false;
+
+- // df_insn_rescan (newii);
+- // df_insn_rescan (newjj);
++ /* add fixes if there were jumps out of the loop. */
++ if (jump_out.size ())
++ {
++ log ("propagate_moves fixing %d jump outs\n", jump_out.size ());
+
+- /* add fixes if there were jumps out of the loop. */
+- if (jump_out.size ())
++ for (unsigned k = 0; k < jump_out.size (); ++k)
+ {
+- log ("propagate_moves fixing %d jump outs\n", jump_out.size ());
+-
+- for (unsigned k = 0; k < jump_out.size (); ++k)
+- {
+- rtx neu = gen_rtx_SET(
+- dstj, gen_rtx_PLUS(Pmode, dsti, gen_rtx_CONST_INT(Pmode, fixups[k])));
+- rtx_insn * neui = emit_insn_after (neu, jump_out[k]);
+- // df_insn_rescan (neui);
+- }
++ rtx neu = gen_rtx_SET(
++ dstj, gen_rtx_PLUS(Pmode, dsti, gen_rtx_CONST_INT(Pmode, fixups[k])));
++ rtx_insn * neui = emit_insn_after (neu, jump_out[k]);
+ }
+- ++change_count;
+ }
++ ++change_count;
+ }
+ }
+ if (inc)
+@@ -1277,8 +1306,6 @@ opt_strcpy ()
+ SET_INSN_DELETED(x2reg);
+ SET_INSN_DELETED(insn);
+
+- // df_insn_rescan (reg2x);
+-
+ ++change_count;
+ }
+ }
+@@ -1394,9 +1421,6 @@ opt_commute_add_move (void)
+
+ add_reg_note (next, REG_INC, reg1dst);
+
+- // df_insn_rescan (insn);
+- // df_insn_rescan (next);
+-
+ ++change_count;
+ }
+ }
+@@ -1579,14 +1603,14 @@ opt_const_cmp_to_sub (void)
+ }
+
+ /*
+- * Some optimizations (e.g. propagate_moves) might result into an unuses assignment behind the loop.
++ * Some optimizations (e.g. propagate_moves) might result into an unused assignment behind the loop.
+ * delete those insns.
+ */
+ static unsigned
+ opt_elim_dead_assign (void)
+ {
+ unsigned change_count = 0;
+- for (unsigned index = 0; index + 1 < insns.size (); ++index)
++ for (int index = insns.size () - 1; index >= 0; --index)
+ {
+ rtx_insn * insn = insns[index];
+ if (!NONJUMP_INSN_P(insn))
+@@ -2186,10 +2210,6 @@ namespace
+ unsigned
+ pass_bbb_optimizations::execute_bbb_optimizations (void)
+ {
+- // df_set_flags (df_LR_RUN_DCE + df_DEFER_INSN_RESCAN);
+- // df_note_add_problem ();
+- // df_analyze ();
+-
+ be_verbose = strchr (string_bbb_opts, 'v');
+
+ bool do_opt_strcpy = strchr (string_bbb_opts, 's') || strchr (string_bbb_opts, '+');
+
+From b02fdbd28177c393c37b5de2448b1a9506a14f82 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 26 Apr 2017 17:50:10 +0200
+Subject: [PATCH 094/303] @B fixed opt_const_cmp_to_sub
+
+---
+ gcc/bbb-opts.c | 81 ++++++++++++++++++++++++----------------------------------
+ 1 file changed, 34 insertions(+), 47 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 9d138063fb27..f0e2f7b58d4c 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -1491,8 +1491,8 @@ opt_const_cmp_to_sub (void)
+ if (!setp)
+ continue;
+
+- rtx dstp = SET_DEST(setp);
+- if (!REG_P(dstp))
++ rtx constant_reg = SET_DEST(setp);
++ if (!REG_P(constant_reg))
+ continue;
+
+ rtx srcp = SET_SRC(setp);
+@@ -1503,34 +1503,20 @@ opt_const_cmp_to_sub (void)
+ if (intval < -8 || intval > 7 || intval == 0)
+ continue;
+
+- enum machine_mode mode = GET_MODE(dstp);
++ enum machine_mode mode = GET_MODE(constant_reg);
+ if (GET_MODE_SIZE(mode) > 4)
+ continue;
+
+ // printf("mode size: %d\n", GET_MODE_SIZE(mode));
+
+- rtx reg = dstp == left ? right : left;
+- rtx plus = gen_rtx_PLUS(mode, copy_reg (reg, -1), gen_rtx_CONST_INT (mode, intval));
+-
+- rtx_insn * neuprev = make_insn_raw (gen_rtx_SET(copy_reg (reg, -1), plus));
++ rtx reg = constant_reg == left ? right : constant_reg == right ? left : 0;
+
+- int num_clobbers_to_add = 0;
+- int insn_code_number = recog (PATTERN (neuprev), neuprev, &num_clobbers_to_add);
+- if (insn_code_number < 0 || !check_asm_operands (PATTERN (neuprev)))
++ // no gain with address regs.
++ if (!reg || REGNO(reg) > 7)
+ continue;
+
+- // also convert current statement to cmp #0, reg
+- SET_INSN_DELETED(insn);
+- rtx neu = gen_rtx_SET(cc0_rtx, gen_rtx_COMPARE(mode, copy_reg(reg, -1), gen_rtx_CONST_INT(mode, 0)));
+- insn = emit_insn_after (neu, prev);
+- add_reg_note (insn, REG_DEAD, reg);
+-
+- SET_INSN_DELETED(prev);
+- prev = emit_insn_before (PATTERN (neuprev), insn);
+-
+- log ("const_cmp_to_sub replaced reg-reg compare with sub\n");
+-
+- if (dstp != left)
++ // search the jump(s)
++ bool ok = true;
+ {
+ // invert all conditions using this statement.
+ std::vector<unsigned> todo;
+@@ -1538,7 +1524,7 @@ opt_const_cmp_to_sub (void)
+ done.resize (insns.size ());
+ todo.push_back (index + 1);
+
+- while (todo.size ())
++ while (ok && todo.size ())
+ {
+ unsigned pos = todo[todo.size () - 1];
+ todo.pop_back ();
+@@ -1555,7 +1541,7 @@ opt_const_cmp_to_sub (void)
+ todo.push_back (pos + 1);
+
+ rtx_insn * patchme = insns[pos];
+- if (!JUMP_P(insn))
++ if (!JUMP_P(patchme))
+ continue;
+
+ std::map<rtx_insn *, unsigned>::iterator j = insn2index.find ((rtx_insn *) JUMP_LABEL(patchme));
+@@ -1569,32 +1555,33 @@ opt_const_cmp_to_sub (void)
+ {
+ rtx condition = XEXP(jmpsrc, 0);
+ RTX_CODE code = GET_CODE(condition);
+- RTX_CODE newcode = code;
+- if (code == GE)
+- newcode = LE;
+- else if (code == GT)
+- newcode = LT;
+- else if (code == LT)
+- newcode = GT;
+- else if (code == LE)
+- newcode = GE;
+- else if (code == GEU)
+- newcode = LEU;
+- else if (code == GTU)
+- newcode = LTU;
+- else if (code == LTU)
+- newcode = GTU;
+- else if (code == LEU)
+- newcode = GEU;
+-
+- if (code != newcode)
+- {
+- log ("patch jcc %d -> %d\n", code, newcode);
+- XEXP(jmpsrc, 0) = gen_rtx_fmt_ee(newcode, VOIDmode, XEXP(condition, 0), XEXP(condition, 1));
+- }
++ ok = code == EQ || code == NE;
+ }
+ }
+ }
++ if (!ok)
++ continue;
++
++ rtx plus = gen_rtx_PLUS(mode, copy_reg (reg, -1), gen_rtx_CONST_INT (mode, intval));
++
++ rtx_insn * neuprev = make_insn_raw (gen_rtx_SET(copy_reg (reg, -1), plus));
++
++ int num_clobbers_to_add = 0;
++ int insn_code_number = recog (PATTERN (neuprev), neuprev, &num_clobbers_to_add);
++ if (insn_code_number < 0 || !check_asm_operands (PATTERN (neuprev)))
++ continue;
++
++ // also convert current statement to cmp #0, reg
++ SET_INSN_DELETED(insn);
++ rtx copyreg = copy_reg (reg, -1);
++ rtx neu = gen_rtx_SET(cc0_rtx, gen_rtx_COMPARE(mode, copyreg, gen_rtx_CONST_INT(mode, 0)));
++ insn = emit_insn_after (neu, prev);
++ add_reg_note (insn, REG_DEAD, copyreg);
++
++ SET_INSN_DELETED(prev);
++ prev = emit_insn_before (PATTERN (neuprev), insn);
++
++ log ("const_cmp_to_sub replaced reg-reg compare with sub\n");
+
+ ++change_count;
+ }
+
+From 67cc3de981f1498e225257ccd4783452e127e58c Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 26 Apr 2017 20:21:59 +0200
+Subject: [PATCH 095/303] @B fix NPE
+
+---
+ gcc/bbb-opts.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index f0e2f7b58d4c..ceb548bea823 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -1551,7 +1551,9 @@ opt_const_cmp_to_sub (void)
+ rtx jmppattern = PATTERN (patchme);
+
+ rtx jmpsrc = XEXP(jmppattern, 1);
+- if (GET_CODE(jmpsrc) == IF_THEN_ELSE)
++ if (!jmpsrc)
++ ok = false;
++ else if (GET_CODE(jmpsrc) == IF_THEN_ELSE)
+ {
+ rtx condition = XEXP(jmpsrc, 0);
+ RTX_CODE code = GET_CODE(condition);
+
+From 17dff22094612ae1f122eec1dad72583a677c1e3 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 27 Apr 2017 17:25:51 +0200
+Subject: [PATCH 096/303] @R some better encapsulation, @D add reg usage to asm
+ source use 'V'
+
+---
+ gcc/bbb-opts.c | 421 +++++++++++++++++++++++++++++++++++----------------------
+ gcc/final.c | 7 +
+ 2 files changed, 264 insertions(+), 164 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index ceb548bea823..32b1aed86ae5 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -66,14 +66,17 @@
+ #include "tree.h"
+ #include "tree-pass.h"
+ #include "conditions.h"
+-#include "cselib.h"
+ #include "langhooks.h"
+ #include <vector>
+ #include <set>
+ #include <map>
+
+-static bool be_verbose;
++bool be_very_verbose;
++bool be_verbose;
+
++#ifdef __ECLIPSE__
++extern char * string_bbb_opts;
++#endif
+ extern struct lang_hooks lang_hooks;
+
+ /* Lookup of the current function name. */
+@@ -116,86 +119,102 @@ log (char const * fmt, ...)
+ *
+ * Track use & def separate to determine starting points.
+ */
+-struct insn_info
++class insn_info
+ {
+- unsigned _use; // bit set if registers are used
+- unsigned _def; // bit set if registers are defined
+- unsigned _hard; // bit set if registers can't be renamed
+-
+- insn_info () :
+- _use (0), _def (0), _hard (0)
++ rtx_insn * insn; // the insn
++ unsigned myuse; // bit set if registers are used in this statement
++ unsigned mydef; // bit set if registers are set in this statement
++ unsigned hard; // bit set if registers can't be renamed
++ unsigned use; // bit set if registers are used in program flow
++ unsigned def; // bit set if registers are defined in program flow
++
++public:
++ insn_info (rtx_insn * i = 0) :
++ insn (i), myuse (0), mydef (0), hard (0), use (0), def (0)
+ {
+ }
+
+ inline void
+ reset ()
+ {
+- _use = 0;
+- _def = 0;
+- _hard = 0;
++ use = 0;
++ def = 0;
++ hard = 0;
++ }
++
++ inline bool
++ is_empty ()
++ {
++ return !def && !use && !hard;
+ }
+
+ inline void
+- use (int regno)
++ mark_use (int regno)
+ {
+- _use |= 1 << regno;
++ myuse |= 1 << regno;
++ use |= 1 << regno;
+ }
+
+ inline void
+- def (int regno)
++ mark_def (int regno)
+ {
+- _def |= 1 << regno;
++ mydef |= 1 << regno;
++ def |= 1 << regno;
+ }
+
+ inline void
+- hard (int regno)
++ mark_hard (int regno)
+ {
+- _hard |= 1 << regno;
++ hard |= 1 << regno;
+ }
+
+ inline void
+ unset (int regno)
+ {
+- _use &= ~(1 << regno);
+- _def &= ~(1 << regno);
+- _hard &= ~(1 << regno);
++ use &= ~(1 << regno);
++ def &= ~(1 << regno);
++ hard &= ~(1 << regno);
++ }
++
++ inline unsigned
++ get_use () const
++ {
++ return use;
++ }
++ inline unsigned
++ get_def () const
++ {
++ return def;
++ }
++ inline unsigned
++ get_hard () const
++ {
++ return hard;
+ }
+
+ inline bool
+ is_use (int regno)
+ {
+- return (_use & (1 << regno)) != 0;
++ return (use & (1 << regno)) != 0;
+ }
+
+ inline bool
+ is_def (int regno)
+ {
+- return (_def & (1 << regno)) != 0;
++ return (def & (1 << regno)) != 0;
+ }
+
+ inline bool
+ is_hard (int regno)
+ {
+- return (_hard & (1 << regno)) != 0;
+- }
+-
+- inline insn_info
+- operator | (insn_info const & o) const
+- {
+- insn_info t;
+- t._use = _use | o._use;
+- t._def = _def | o._def;
+- t._hard = _hard | o._hard;
+- return t;
++ return (hard & (1 << regno)) != 0;
+ }
+
+- inline insn_info &
+- operator |= (insn_info const & o)
++ inline void
++ clear_hard_def ()
+ {
+- _use |= o._use;
+- _def |= o._def;
+- _hard |= o._hard;
+- return *this;
++ hard = 0;
++ def = 0;
+ }
+
+ /*
+@@ -208,106 +227,155 @@ struct insn_info
+ inline void
+ updateWith (insn_info const & o)
+ {
+- _use &= ~o._def;
+- _use |= o._use;
+- _def = 0;
++ use &= ~o.def;
++ use |= o.use;
++ def = 0;
+ }
+
+- inline bool
+- operator == (insn_info const & o)
++ inline insn_info &
++ merge (insn_info const & o)
+ {
+- return _use == o._use;
++ use = (use & ~o.def) | o.use;
++ def |= o.def;
++ hard |= o.hard;
++ return *this;
++ }
++
++ inline insn_info &
++ drop_def ()
++ {
++ use &= ~def;
++ return *this;
+ }
+
++#if 0
++ inline insn_info
++ operator | (insn_info const & o) const
++ {
++ insn_info t;
++ t.use = use | o.use;
++ t.def = def | o.def;
++ t.hard = hard | o.hard;
++ return t;
++ }
++
++ inline bool
++ operator == (insn_info const & o)
++ {
++ return use == o.use;
++ }
++
+ inline insn_info
+ operator ~ () const
++ {
++ insn_info t;
++ t.use = ~use;
++ t.def = ~def;
++ t.hard = ~hard;
++ return t;
++ }
++#endif
++
++ inline insn_info &
++ make_hard ()
++ {
++ hard = use | def;
++ return *this;
++ }
++
++ inline insn_info &
++ make_clobber ()
+ {
+- insn_info t;
+- t._use = ~_use;
+- t._def = ~_def;
+- t._hard = ~_hard;
+- return t;
++ hard = use = def = use | def;
++ return *this;
+ }
+
+ inline bool
+ contains (insn_info const & o) const
+ {
+- if (o._def & ~_def)
++ if (o.def & ~def)
+ return false;
+- if (o._use & ~_use)
++ if (o.use & ~use)
+ return false;
+- if (o._hard & ~_hard)
++ if (o.hard & ~hard)
+ return false;
+ return true;
+ }
+
+ void
+- scan_call (rtx_insn *);
++ scan ();
+
+ void
+- scan (rtx);
++ scan_rtx (rtx);
+
+ /* return bits for alternate free registers. */
+ unsigned
+ get_free_mask () const
+ {
+- if (_def & _hard)
++ if (def & hard)
+ return 0;
+
+- if (!_def || _def > 0x1000)
++ if (!def || def > 0x1000)
+ return 0;
+
+- unsigned mask = _def - 1;
++ unsigned mask = def - 1;
+ /* more than one register -> don't touch. */
+- if ((mask & ~_def) != mask)
++ if ((mask & ~def) != mask)
+ return 0;
+
+- if (_def > 0xff)
++ if (def > 0xff)
+ mask &= 0xff00;
+
+- return mask & ~_use;
++ return mask & ~use;
++ }
++
++ unsigned
++ get_regbit () const
++ {
++ return def & ~hard & ~use & 0x7fff;
+ }
+ };
+
+ void
+-insn_info::scan_call (rtx_insn * insn)
++insn_info::scan ()
+ {
+- /* add mregparm registers. */
+- for (rtx link = CALL_INSN_FUNCTION_USAGE(insn); link; link = XEXP(link, 1))
++ rtx pattern = PATTERN (insn);
++ if (CALL_P(insn))
+ {
+- rtx op, reg;
++ /* add mregparm registers. */
++ for (rtx link = CALL_INSN_FUNCTION_USAGE(insn); link; link = XEXP(link, 1))
++ {
++ rtx op, reg;
+
+- if (GET_CODE (op = XEXP (link, 0)) == USE && REG_P(reg = XEXP (op, 0)))
+- for (unsigned r = REGNO(reg); r <= END_REGNO (reg); ++r)
+- use (r);
++ if (GET_CODE (op = XEXP (link, 0)) == USE && REG_P(reg = XEXP (op, 0)))
++ for (unsigned r = REGNO(reg); r <= END_REGNO (reg); ++r)
++ mark_use (r);
++ }
++ /* mark scratch registers. */
++ mark_def (0);
++ mark_def (1);
++ mark_def (8);
++ mark_def (9);
++ /* also mark all registers as not renamable */
++ hard = use;
+ }
+- /* also mark all registers as not renamable */
+- _hard = _use;
+-
+- scan (PATTERN (insn));
+-
+- /* mark scratch registers. */
+- def (0);
+- def (1);
+- def (8);
+- def (9);
+-
++ scan_rtx (pattern);
+ }
+
+ /* scan rtx for registers and set the corresponding flags. */
+ void
+-insn_info::scan (rtx x)
++insn_info::scan_rtx (rtx x)
+ {
+ if (REG_P(x))
+ {
+ for (int n = REG_NREGS(x), r = REGNO(x); n > 0; --n, ++r)
+- use (r);
++ mark_use (r);
+ return;
+ }
+
+ if (x == cc0_rtx)
+ {
+- use (FIRST_PSEUDO_REGISTER);
++ mark_use (FIRST_PSEUDO_REGISTER);
+ return;
+ }
+
+@@ -316,17 +384,17 @@ insn_info::scan (rtx x)
+ /* handle SET and record use and def. */
+ if (code == SET)
+ {
+- unsigned u = _use;
+- scan (SET_DEST(x));
++ unsigned u = use;
++ scan_rtx (SET_DEST(x));
+ if (REG_P(SET_DEST(x)))
+ {
+- _def |= _use;
+- _use = u;
++ def |= use;
++ use = u;
+ }
+- scan (SET_SRC(x));
++ scan_rtx (SET_SRC(x));
+ int code = GET_CODE(SET_SRC(x));
+ if (code == ASM_OPERANDS)
+- _use = _hard |= _def | _use;
++ use = hard |= def | use;
+ return;
+ }
+
+@@ -334,10 +402,10 @@ insn_info::scan (rtx x)
+ for (int i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'e')
+- scan (XEXP(x, i));
++ scan_rtx (XEXP(x, i));
+ else if (fmt[i] == 'E')
+ for (int j = XVECLEN (x, i) - 1; j >= 0; j--)
+- scan (XVECEXP(x, i, j));
++ scan_rtx (XVECEXP(x, i, j));
+ }
+ }
+
+@@ -429,7 +497,7 @@ is_reg_dead (unsigned regno, unsigned _pos)
+ {
+ insn_info & ii0 = infos[pos];
+ // skip entries without info
+- if (!ii0._def && !ii0._use && !ii0._hard)
++ if (ii0.is_empty ())
+ continue;
+
+ // not dead if usage is reported in the next statement
+@@ -438,6 +506,45 @@ is_reg_dead (unsigned regno, unsigned _pos)
+ return true;
+ }
+
++/* helper stuff to enhance the asm output. */
++int my_flag_regusage;
++void
++append_reg_usage (FILE * f, rtx_insn * insn)
++{
++
++ auto i = insn2index.find (insn);
++ if (i == insn2index.end ())
++ return;
++
++ insn_info & ii = infos[i->second];
++
++ fprintf (f, "\n\t\t\t\t\t\t| ");
++
++ for (int j = 0; j < 8; ++j)
++ if (ii.is_use (j) || ii.is_def (j))
++ {
++ fprintf (f, ii.is_hard (j) ? "!" : " ");
++ fprintf (f, ii.is_def (j) ? ii.is_use (j) ? "*" : "+" : " ");
++ fprintf (f, "d%d ", j);
++ }
++ else
++ fprintf (f, " ");
++
++ for (int j = 8; j < 16; ++j)
++ if (ii.is_use (j) || ii.is_def (j))
++ {
++ fprintf (f, ii.is_hard (j) ? "!" : " ");
++ fprintf (f, ii.is_def (j) ? ii.is_use (j) ? "*" : "+" : " ");
++ fprintf (f, "a%d ", j - 8);
++ }
++ else
++ fprintf (f, " ");
++
++ if (ii.is_use (FIRST_PSEUDO_REGISTER))
++ fprintf (f, ii.is_def (FIRST_PSEUDO_REGISTER) ? "*cc " : "cc ");
++
++}
++
+ /*
+ * Helper function to dump the code.
+ * Sometimes used during debugging.
+@@ -456,33 +563,7 @@ dump_insns (char const * name, bool all)
+ fprintf (stderr, "%d: ", i);
+
+ if (i < infos.size ())
+- {
+- insn_info & ii = infos[i];
+-
+- for (int j = 0; j < 8; ++j)
+- if (ii.is_use (j) || ii.is_def (j))
+- {
+- if (ii.is_hard (j))
+- fprintf (stderr, "!");
+- if (ii.is_def (j))
+- fprintf (stderr, "*");
+- fprintf (stderr, "d%d ", j);
+- }
+-
+- for (int j = 8; j < 16; ++j)
+- if (ii.is_use (j) || ii.is_def (j))
+- {
+- if (ii.is_hard (j))
+- fprintf (stderr, "!");
+- if (ii.is_def (j))
+- fprintf (stderr, "*");
+- fprintf (stderr, "a%d ", j - 8);
+- }
+-
+- if (ii.is_use (FIRST_PSEUDO_REGISTER))
+- fprintf (stderr, ii.is_def (FIRST_PSEUDO_REGISTER) ? "*cc " : "cc ");
+-
+- }
++ append_reg_usage (stderr, insns[i]);
+
+ fprintf (stderr, "\t");
+ debug_rtx (insns[i]);
+@@ -569,8 +650,8 @@ update_insn_infos (void)
+ if (pass && infos[pos].contains (ii))
+ break;
+
+- ii._hard = 0;
+- ii |= infos[pos];
++ ii.clear_hard_def ();
++ ii.merge (infos[pos]);
+
+ if (LABEL_P(insn))
+ {
+@@ -591,10 +672,11 @@ update_insn_infos (void)
+
+ if (CALL_P(insn))
+ {
+- insn_info use;
+- use.scan_call (insn);
++ insn_info use (insn);
++ use.scan ();
+
+- infos[pos] = use | ii;
++ ii.merge (use);
++ infos[pos] = ii;
+ ii.updateWith (use);
+
+ continue;
+@@ -602,7 +684,7 @@ update_insn_infos (void)
+
+ if (JUMP_P(insn))
+ {
+- insn_info use;
++ insn_info use (insn);
+ if (ANY_RETURN_P(pattern))
+ {
+ tree type = TYPE_SIZE(TREE_TYPE (DECL_RESULT (current_function_decl)));
+@@ -610,19 +692,20 @@ update_insn_infos (void)
+ // log ("return size %d\n", sz);
+ if (sz <= 64)
+ {
+- use.hard (0);
+- use.use (0);
++ use.mark_hard (0);
++ use.mark_use (0);
+ if (sz > 32)
+ {
+- use.hard (1);
+- use.use (1);
++ use.mark_hard (1);
++ use.mark_use (1);
+ }
+ }
+ ii.reset ();
+ }
+
+- use.scan (pattern);
+- infos[pos] = use | ii;
++ use.scan ();
++ ii.merge (use);
++ infos[pos] = ii;
+ ii.updateWith (use);
+
+ continue;
+@@ -630,31 +713,41 @@ update_insn_infos (void)
+
+ if (GET_CODE (pattern) == USE)
+ {
+- rtx x = XEXP(pattern, 0);
+- if (REG_P(x))
+- {
+- ii.use (REGNO(x));
+- ii.hard (REGNO(x));
+- }
++ insn_info use (insn);
++ use.scan ();
++ use.make_clobber ();
++
++ ii.merge (use);
+ infos[pos] = ii;
++ ii.updateWith (use);
++
++// rtx x = XEXP(pattern, 0);
++// if (REG_P(x))
++// {
++// ii.mark_use (REGNO(x));
++// ii.mark_hard (REGNO(x));
++// }
++// infos[pos] = ii;
+ continue;
+ }
+
+ if (GET_CODE (pattern) == CLOBBER)
+ {
+ /* mark regs as use and def */
+- insn_info use;
+- use.scan (pattern);
+- use._hard = use._use = use._def = use._use | use._def;
+- infos[pos] = use | ii;
++ insn_info use (insn);
++ use.scan ();
++ use.make_clobber ();
++ ii.merge (use);
++ infos[pos] = ii;
+ ii.updateWith (use);
+ continue;
+ }
+
+- insn_info use;
+- use.scan (pattern);
++ insn_info use (insn);
++ use.scan ();
++
+ if (single_set (insn) == 0)
+- use._hard = use._use | use._def;
++ use.make_hard ();
+ else
+ /* if not cc0 defined check for mod. */
+ if (!use.is_def (FIRST_PSEUDO_REGISTER))
+@@ -662,15 +755,15 @@ update_insn_infos (void)
+ CC_STATUS_INIT;
+ NOTICE_UPDATE_CC(PATTERN (insn), insn);
+ if (cc_status.value1 || cc_status.value2)
+- use.def (FIRST_PSEUDO_REGISTER);
++ use.mark_def (FIRST_PSEUDO_REGISTER);
+ }
+
+ /* mark not renameable in prologue/epilogue. */
+ if (proepilogue[pos])
+- use._hard = use._use | use._def;
++ use.make_hard ();
+
+- ii._use &= ~use._def;
+- infos[pos] = use | ii;
++ ii.merge (use);
++ infos[pos] = ii;
+ ii.updateWith (use);
+ }
+ ++pass;
+@@ -699,12 +792,12 @@ is_reg_touched_between (unsigned regno, int from, int to)
+ {
+ for (int index = from + 1; index < to; ++index)
+ {
+- insn_info ii;
+ rtx_insn * insn = insns[index];
++ insn_info ii (insn);
+ if (CALL_P(insn))
+- ii.scan_call (insn);
++ ii.scan ();
+ else
+- ii.scan (PATTERN (insn));
++ ii.scan_rtx (PATTERN (insn));
+ if (ii.is_use (regno) || ii.is_def (regno))
+ return true;
+ }
+@@ -754,7 +847,7 @@ opt_reg_rename (void)
+ insn_info & ii = infos[index];
+
+ /* do not rename if register is hard or used in same statement. */
+- const unsigned rename_regbit = ii._def & ~ii._hard & ~ii._use;
++ const unsigned rename_regbit = ii.get_regbit ();
+ if (!rename_regbit)
+ continue;
+
+@@ -819,7 +912,7 @@ opt_reg_rename (void)
+ insn_info & jj = infos[pos];
+
+ /* marked as hard reg -> invalid rename */
+- if (jj._use & jj._hard & rename_regbit)
++ if (jj.get_use () & jj.get_hard () & rename_regbit)
+ mask = 0;
+
+ // /* defined again -> invalid rename */
+@@ -830,16 +923,16 @@ opt_reg_rename (void)
+ break;
+
+ /* not used. and not a def */
+- if (pos == runpos && (jj._def & rename_regbit))
++ if (pos == runpos && (jj.get_def () & rename_regbit))
+ {
+ /* continue since this pos was added by start search. */
+ }
+- else if (!(jj._use & rename_regbit))
++ else if (!(jj.get_use () & rename_regbit))
+ break;
+
+ /* update free regs. */
+- mask &= ~jj._use;
+- mask &= ~jj._def;
++ mask &= ~jj.get_use ();
++ mask &= ~jj.get_def ();
+ if (!mask)
+ break;
+
+@@ -1616,7 +1709,7 @@ opt_elim_dead_assign (void)
+
+ if (is_reg_dead (REGNO(dst), index))
+ {
+- log ("elim_dead_assign to %s\n", reg_names[REGNO(dst)]);
++ log ("%d: elim_dead_assign to %s\n", index, reg_names[REGNO(dst)]);
+ SET_INSN_DELETED(insn);
+ ++change_count;
+ }
+@@ -1897,9 +1990,9 @@ opt_shrink_stack_frame (void)
+ continue;
+
+ insn_info & jj = infos[i];
+- ii |= jj;
++ ii.merge (jj);
+ }
+- unsigned freemask = ~ii._use;
++ unsigned freemask = ~ii.get_use ();
+
+ rtx a7 = gen_raw_REG (SImode, STACK_POINTER_REGNUM);
+ rtx a5 = gen_raw_REG (SImode, FRAME_POINTER_REGNUM);
+@@ -2123,9 +2216,9 @@ opt_shrink_stack_frame (void)
+ continue;
+
+ insn_info & jj = infos[i];
+- ii |= jj;
++ ii.merge (jj);
+ }
+- unsigned freemask = ~ii._use;
++ unsigned freemask = ~ii.get_use ();
+
+ if (freemask & (1 << FRAME_POINTER_REGNUM))
+ {
+@@ -2199,7 +2292,8 @@ namespace
+ unsigned
+ pass_bbb_optimizations::execute_bbb_optimizations (void)
+ {
+- be_verbose = strchr (string_bbb_opts, 'v');
++ be_very_verbose = strchr (string_bbb_opts, 'V');
++ be_verbose = be_very_verbose || strchr (string_bbb_opts, 'v');
+
+ bool do_opt_strcpy = strchr (string_bbb_opts, 's') || strchr (string_bbb_opts, '+');
+ bool do_commute_add_move = strchr (string_bbb_opts, 'a') || strchr (string_bbb_opts, '+');
+@@ -2257,7 +2351,6 @@ namespace
+
+ if (strchr (string_bbb_opts, 'X') || strchr (string_bbb_opts, 'x'))
+ dump_insns ("bbb", strchr (string_bbb_opts, 'X'));
+- clear ();
+
+ return 0;
+ }
+diff --git a/gcc/final.c b/gcc/final.c
+index 31f9b4815d75..94c96470e019 100644
+--- gcc/final.c
++++ gcc/final.c
+@@ -2151,6 +2151,7 @@ call_from_call_insn (rtx_call_insn *insn)
+ SEEN is used to track the end of the prologue, for emitting
+ debug information. We force the emission of a line note after
+ both NOTE_INSN_PROLOGUE_END and NOTE_INSN_FUNCTION_BEG. */
++rtx_insn * current_insn;
+
+ rtx_insn *
+ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
+@@ -2160,6 +2161,7 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
+ rtx set;
+ #endif
+ rtx_insn *next;
++ current_insn = insn;
+
+ insn_counter++;
+
+@@ -3622,6 +3624,8 @@ do_assembler_dialects (const char *p, int *dialect)
+ void
+ output_asm_insn (const char *templ, rtx *operands)
+ {
++ extern bool be_very_verbose;
++ extern void append_reg_usage(FILE *, rtx_insn *);
+ const char *p;
+ int c;
+ #ifdef ASSEMBLER_DIALECT
+@@ -3778,6 +3782,9 @@ output_asm_insn (const char *templ, rtx *operands)
+ putc (c, asm_out_file);
+ }
+
++ if (be_very_verbose)
++ append_reg_usage(asm_out_file, current_insn);
++
+ /* Write out the variable names for operands, if we know them. */
+ if (flag_verbose_asm)
+ output_asm_operand_names (operands, oporder, ops);
+
+From c61d5d9c3e2f1376ab8f4a9783a1fc5e9c283f3c Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 27 Apr 2017 22:27:45 +0200
+Subject: [PATCH 097/303] @R some better encapsulation
+
+---
+ gcc/bbb-opts.c | 136 ++++++++++++++++++---------------------------------------
+ 1 file changed, 43 insertions(+), 93 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 32b1aed86ae5..439223bf6f87 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -123,14 +123,13 @@ class insn_info
+ {
+ rtx_insn * insn; // the insn
+ unsigned myuse; // bit set if registers are used in this statement
+- unsigned mydef; // bit set if registers are set in this statement
+ unsigned hard; // bit set if registers can't be renamed
+ unsigned use; // bit set if registers are used in program flow
+- unsigned def; // bit set if registers are defined in program flow
++ unsigned def; // bit set if registers are defined here
+
+ public:
+ insn_info (rtx_insn * i = 0) :
+- insn (i), myuse (0), mydef (0), hard (0), use (0), def (0)
++ insn (i), myuse (0), hard (0), use (0), def (0)
+ {
+ }
+
+@@ -158,7 +157,6 @@ class insn_info
+ inline void
+ mark_def (int regno)
+ {
+- mydef |= 1 << regno;
+ def |= 1 << regno;
+ }
+
+@@ -198,6 +196,12 @@ class insn_info
+ return (use & (1 << regno)) != 0;
+ }
+
++ inline bool
++ is_myuse (int regno)
++ {
++ return (myuse & (1 << regno)) != 0;
++ }
++
+ inline bool
+ is_def (int regno)
+ {
+@@ -340,7 +344,23 @@ void
+ insn_info::scan ()
+ {
+ rtx pattern = PATTERN (insn);
+- if (CALL_P(insn))
++ if (ANY_RETURN_P(pattern))
++ {
++ tree type = TYPE_SIZE(TREE_TYPE (DECL_RESULT (current_function_decl)));
++ int sz = type ? TREE_INT_CST_LOW(type) : 0;
++ // log ("return size %d\n", sz);
++ if (sz <= 64)
++ {
++ mark_hard (0);
++ mark_use (0);
++ if (sz > 32)
++ {
++ mark_hard (1);
++ mark_use (1);
++ }
++ }
++ }
++ else if (CALL_P(insn))
+ {
+ /* add mregparm registers. */
+ for (rtx link = CALL_INSN_FUNCTION_USAGE(insn); link; link = XEXP(link, 1))
+@@ -385,11 +405,13 @@ insn_info::scan_rtx (rtx x)
+ if (code == SET)
+ {
+ unsigned u = use;
++ unsigned mu = myuse;
+ scan_rtx (SET_DEST(x));
+ if (REG_P(SET_DEST(x)))
+ {
+ def |= use;
+ use = u;
++ myuse = mu;
+ }
+ scan_rtx (SET_SRC(x));
+ int code = GET_CODE(SET_SRC(x));
+@@ -518,13 +540,14 @@ append_reg_usage (FILE * f, rtx_insn * insn)
+
+ insn_info & ii = infos[i->second];
+
+- fprintf (f, "\n\t\t\t\t\t\t| ");
++ if (f != stderr)
++ fprintf (f, "\n\t\t\t\t\t\t| ");
+
+ for (int j = 0; j < 8; ++j)
+ if (ii.is_use (j) || ii.is_def (j))
+ {
+ fprintf (f, ii.is_hard (j) ? "!" : " ");
+- fprintf (f, ii.is_def (j) ? ii.is_use (j) ? "*" : "+" : " ");
++ fprintf (f, ii.is_def (j) ? ii.is_use (j) ? "*" : "+" : " ");
+ fprintf (f, "d%d ", j);
+ }
+ else
+@@ -534,14 +557,14 @@ append_reg_usage (FILE * f, rtx_insn * insn)
+ if (ii.is_use (j) || ii.is_def (j))
+ {
+ fprintf (f, ii.is_hard (j) ? "!" : " ");
+- fprintf (f, ii.is_def (j) ? ii.is_use (j) ? "*" : "+" : " ");
++ fprintf (f, ii.is_def (j) ? ii.is_use (j) ? "*" : "+" : " ");
+ fprintf (f, "a%d ", j - 8);
+ }
+ else
+ fprintf (f, " ");
+
+ if (ii.is_use (FIRST_PSEUDO_REGISTER))
+- fprintf (f, ii.is_def (FIRST_PSEUDO_REGISTER) ? "*cc " : "cc ");
++ fprintf (f, ii.is_def (FIRST_PSEUDO_REGISTER) ? "+cc " : " cc ");
+
+ }
+
+@@ -669,84 +692,24 @@ update_insn_infos (void)
+ }
+
+ rtx pattern = PATTERN (insn);
++ insn_info use (insn);
++ use.scan ();
+
+ if (CALL_P(insn))
+ {
+- insn_info use (insn);
+- use.scan ();
+-
+- ii.merge (use);
+- infos[pos] = ii;
+- ii.updateWith (use);
+-
+- continue;
+ }
+-
+- if (JUMP_P(insn))
++ else if (JUMP_P(insn))
+ {
+- insn_info use (insn);
+ if (ANY_RETURN_P(pattern))
+ {
+- tree type = TYPE_SIZE(TREE_TYPE (DECL_RESULT (current_function_decl)));
+- int sz = type ? TREE_INT_CST_LOW(type) : 0;
+- // log ("return size %d\n", sz);
+- if (sz <= 64)
+- {
+- use.mark_hard (0);
+- use.mark_use (0);
+- if (sz > 32)
+- {
+- use.mark_hard (1);
+- use.mark_use (1);
+- }
+- }
+ ii.reset ();
+ }
+-
+- use.scan ();
+- ii.merge (use);
+- infos[pos] = ii;
+- ii.updateWith (use);
+-
+- continue;
+ }
+-
+- if (GET_CODE (pattern) == USE)
+- {
+- insn_info use (insn);
+- use.scan ();
+- use.make_clobber ();
+-
+- ii.merge (use);
+- infos[pos] = ii;
+- ii.updateWith (use);
+-
+-// rtx x = XEXP(pattern, 0);
+-// if (REG_P(x))
+-// {
+-// ii.mark_use (REGNO(x));
+-// ii.mark_hard (REGNO(x));
+-// }
+-// infos[pos] = ii;
+- continue;
+- }
+-
+- if (GET_CODE (pattern) == CLOBBER)
++ else if (GET_CODE (pattern) == USE || GET_CODE (pattern) == CLOBBER)
+ {
+- /* mark regs as use and def */
+- insn_info use (insn);
+- use.scan ();
+ use.make_clobber ();
+- ii.merge (use);
+- infos[pos] = ii;
+- ii.updateWith (use);
+- continue;
+ }
+-
+- insn_info use (insn);
+- use.scan ();
+-
+- if (single_set (insn) == 0)
++ else if (single_set (insn) == 0)
+ use.make_hard ();
+ else
+ /* if not cc0 defined check for mod. */
+@@ -792,13 +755,8 @@ is_reg_touched_between (unsigned regno, int from, int to)
+ {
+ for (int index = from + 1; index < to; ++index)
+ {
+- rtx_insn * insn = insns[index];
+- insn_info ii (insn);
+- if (CALL_P(insn))
+- ii.scan ();
+- else
+- ii.scan_rtx (PATTERN (insn));
+- if (ii.is_use (regno) || ii.is_def (regno))
++ insn_info & ii = infos[index];
++ if (ii.is_myuse (regno) || ii.is_def (regno))
+ return true;
+ }
+ return false;
+@@ -864,10 +822,6 @@ opt_reg_rename (void)
+ if (index + 1 < insns.size ())
+ todo.push_back (index + 1);
+
+-// /* trigger jump checking */
+-// if (index > 0 && LABEL_P(insns[index - 1]))
+-// todo.push_back (std::make_pair(index - 1, 0));
+-
+ found.insert (index);
+ /* a register was defined, follow all branches. */
+ while (mask && todo.size ())
+@@ -913,14 +867,10 @@ opt_reg_rename (void)
+
+ /* marked as hard reg -> invalid rename */
+ if (jj.get_use () & jj.get_hard () & rename_regbit)
+- mask = 0;
+-
+-// /* defined again -> invalid rename */
+-// if ((jj._def & rename_regbit) && !(jj._use & rename_regbit))
+-// mask = 0;
+-
+- if (!mask)
+- break;
++ {
++ mask = 0;
++ break;
++ }
+
+ /* not used. and not a def */
+ if (pos == runpos && (jj.get_def () & rename_regbit))
+
+From 63bb3cbeae6aa5780413e18a8bfe23873dc310f5 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 27 Apr 2017 23:00:26 +0200
+Subject: [PATCH 098/303] @R some better encapsulation
+
+---
+ gcc/bbb-opts.c | 228 ++++++++++++++++++++++++++++++---------------------------
+ 1 file changed, 120 insertions(+), 108 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 439223bf6f87..fc4acc87a0a9 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -126,11 +126,50 @@ class insn_info
+ unsigned hard; // bit set if registers can't be renamed
+ unsigned use; // bit set if registers are used in program flow
+ unsigned def; // bit set if registers are defined here
++ int proepi; // 1 = in prologue, 2 = in epilogue, 0 = other
++ bool stack; // part of stack frame insns
++
++ insn_info &
++ operator = (insn_info const &);
+
+ public:
+- insn_info (rtx_insn * i = 0) :
+- insn (i), myuse (0), hard (0), use (0), def (0)
++ insn_info (rtx_insn * i = 0, int p = 0) :
++ insn (i), myuse (0), hard (0), use (0), def (0), proepi (p), stack (false)
++ {
++ }
++
++ /* update usage. */
++ void
++ update (insn_info & o)
++ {
++ myuse = o.myuse;
++ hard = o.hard;
++ use = o.use;
++ def = o.def;
++ }
++
++ inline rtx_insn *
++ get_insn () const
++ {
++ return insn;
++ }
++
++ void
++ mark_stack ()
++ {
++ stack = true;
++ }
++
++ bool
++ is_stack () const
++ {
++ return stack;
++ }
++
++ inline int
++ in_proepi () const
+ {
++ return proepi;
+ }
+
+ inline void
+@@ -487,12 +526,9 @@ temp_reg_rename (std::vector<std::pair<rtx *, rtx> > & loc, rtx x, unsigned oldr
+ /*
+ * Collect some data.
+ */
+-static std::vector<rtx_insn *> insns;
+-static std::vector<char> proepilogue;
+-static std::vector<rtx_insn *> temp;
++static std::vector<insn_info> infos;
+ static std::vector<rtx_insn *> jumps;
+ static std::map<rtx_insn *, unsigned> insn2index;
+-static std::vector<insn_info> infos;
+
+ /*
+ * Reset collected data.
+@@ -500,8 +536,6 @@ static std::vector<insn_info> infos;
+ static void
+ clear (void)
+ {
+- insns.clear ();
+- proepilogue.clear ();
+ jumps.clear ();
+ insn2index.clear ();
+ infos.clear ();
+@@ -578,23 +612,24 @@ dump_insns (char const * name, bool all)
+ fprintf (stderr, "====================================: %s\n", name);
+ if (all)
+ {
+- for (rtx_insn * insn = get_insns (); insn && insn != insns[0]; insn = NEXT_INSN (insn))
++ for (rtx_insn * insn = get_insns (); insn && insn != infos[0].get_insn (); insn = NEXT_INSN (insn))
+ debug_rtx (insn);
+ }
+- for (unsigned i = 0; i < insns.size (); ++i)
++ for (unsigned i = 0; i < infos.size (); ++i)
+ {
+ fprintf (stderr, "%d: ", i);
+
++ rtx_insn * insn = infos[i].get_insn ();
+ if (i < infos.size ())
+- append_reg_usage (stderr, insns[i]);
++ append_reg_usage (stderr, insn);
+
+ fprintf (stderr, "\t");
+- debug_rtx (insns[i]);
++ debug_rtx (insn);
+
+ if (all)
+ {
+- rtx_insn * p = i + 1 < insns.size () ? insns[i + 1] : 0;
+- for (rtx_insn * q = NEXT_INSN (insns[i]); q && q != p; q = NEXT_INSN (q))
++ rtx_insn * p = i + 1 < infos.size () ? infos[i + 1].get_insn () : 0;
++ for (rtx_insn * q = NEXT_INSN (insn); q && q != p; q = NEXT_INSN (q))
+ debug_rtx (q);
+ }
+ }
+@@ -620,9 +655,8 @@ update_insns ()
+ if (JUMP_P(insn))
+ jumps.push_back (insn);
+
+- insn2index.insert (std::make_pair (insn, insns.size ()));
+- insns.push_back (insn);
+- proepilogue.push_back (inproepilogue);
++ insn2index.insert (std::make_pair (insn, infos.size ()));
++ infos.push_back (insn_info (insn, inproepilogue));
+
+ if (JUMP_P(insn))
+ inproepilogue = 0;
+@@ -647,12 +681,9 @@ update_insns ()
+ static void
+ update_insn_infos (void)
+ {
+- /* prepare insn_info */
+- infos.resize (insns.size ());
+-
+ /* own analyze reg life */
+ std::vector<std::pair<unsigned, insn_info> > todo;
+- todo.push_back (std::make_pair (insns.size () - 1, insn_info ()));
++ todo.push_back (std::make_pair (infos.size () - 1, insn_info ()));
+
+ int pass = 0;
+ while (!todo.empty ())
+@@ -664,7 +695,7 @@ update_insn_infos (void)
+
+ for (int pos = p.first; pos >= 0; --pos)
+ {
+- rtx_insn * insn = insns[pos];
++ rtx_insn * insn = infos[pos].get_insn ();
+ /* can be NULL as used in opt_shrink_stack_frame(). */
+ if (!insn)
+ continue;
+@@ -679,7 +710,7 @@ update_insn_infos (void)
+ if (LABEL_P(insn))
+ {
+ /* work on all jumps referring to that label. */
+- for (std::vector<rtx_insn *>::iterator i = jumps.begin (); i != jumps.end (); ++i)
++ for (auto i = jumps.begin (); i != jumps.end (); ++i)
+ {
+ if (JUMP_LABEL(*i) == insn)
+ {
+@@ -722,11 +753,11 @@ update_insn_infos (void)
+ }
+
+ /* mark not renameable in prologue/epilogue. */
+- if (proepilogue[pos])
++ if (infos[pos].in_proepi ())
+ use.make_hard ();
+
+ ii.merge (use);
+- infos[pos] = ii;
++ infos[pos].update (ii);
+ ii.updateWith (use);
+ }
+ ++pass;
+@@ -778,7 +809,7 @@ find_start (std::set<unsigned> & found, unsigned start, unsigned rename_regno)
+ break;
+
+ /* do not run over RETURNS */
+- rtx_insn * before = insns[startm1];
++ rtx_insn * before = infos[startm1].get_insn ();
+ if (JUMP_P(before) && ANY_RETURN_P(PATTERN (before)))
+ break;
+
+@@ -800,7 +831,7 @@ static unsigned
+ opt_reg_rename (void)
+ {
+ // dump_insns ("rename", 1);
+- for (unsigned index = 0; index < insns.size (); ++index)
++ for (unsigned index = 0; index < infos.size (); ++index)
+ {
+ insn_info & ii = infos[index];
+
+@@ -819,7 +850,7 @@ opt_reg_rename (void)
+ /* first = pos to start, second indicates to treat def as use. */
+ std::vector<unsigned> todo;
+ std::set<unsigned> found;
+- if (index + 1 < insns.size ())
++ if (index + 1 < infos.size ())
+ todo.push_back (index + 1);
+
+ found.insert (index);
+@@ -829,13 +860,13 @@ opt_reg_rename (void)
+ unsigned runpos = todo[todo.size () - 1];
+ todo.pop_back ();
+
+- for (unsigned pos = runpos; mask && pos < insns.size (); ++pos)
++ for (unsigned pos = runpos; mask && pos < infos.size (); ++pos)
+ {
+ /* already searched. */
+ if (found.find (pos) != found.end ())
+ break;
+
+- rtx_insn * insn = insns[pos];
++ rtx_insn * insn = infos[pos].get_insn ();
+ if (LABEL_P(insn))
+ {
+ found.insert (pos);
+@@ -844,7 +875,7 @@ opt_reg_rename (void)
+ * check if the reg was used at that jump.
+ * if used, find def
+ */
+- for (std::vector<rtx_insn *>::iterator i = jumps.begin (); i != jumps.end (); ++i)
++ for (auto i = jumps.begin (); i != jumps.end (); ++i)
+ {
+ if (JUMP_LABEL(*i) == insn)
+ {
+@@ -940,7 +971,7 @@ opt_reg_rename (void)
+
+ for (std::set<unsigned>::iterator i = found.begin (); ok && i != found.end (); ++i)
+ {
+- rtx_insn * insn = insns[*i];
++ rtx_insn * insn = infos[*i].get_insn ();
+
+ /* temp rename. */
+ temp_reg_rename (locs, PATTERN (insn), oldregno, newregno);
+@@ -1044,9 +1075,9 @@ opt_propagate_moves ()
+ std::vector<rtx_insn *> jump_out;
+
+ /* start at 1 since there must be an insn before the label. */
+- for (unsigned index = 1; index < insns.size (); ++index)
++ for (unsigned index = 1; index < infos.size (); ++index)
+ {
+- rtx_insn * insn = insns[index];
++ rtx_insn * insn = infos[index].get_insn ();
+
+ if (LABEL_P(insn))
+ {
+@@ -1103,11 +1134,11 @@ opt_propagate_moves ()
+ bool inc = true;
+ for (std::vector<unsigned>::iterator j = i + 1; j != reg_reg.end ();)
+ {
+- rtx_insn * ii = insns[*i];
++ rtx_insn * ii = infos[*i].get_insn ();
+ rtx seti = single_set (ii);
+ rtx srci = SET_SRC(seti);
+ rtx dsti = SET_DEST(seti);
+- rtx_insn * jj = insns[*j];
++ rtx_insn * jj = infos[*j].get_insn ();
+ rtx setj = single_set (jj);
+ rtx srcj = SET_SRC(setj);
+ rtx dstj = SET_DEST(setj);
+@@ -1139,7 +1170,7 @@ opt_propagate_moves ()
+
+ for (unsigned k = *i + 1; k != *j; ++k)
+ {
+- rtx_insn * check = insns[k];
++ rtx_insn * check = infos[k].get_insn ();
+ if (JUMP_P(check))
+ {
+ fixups.push_back (fixup);
+@@ -1204,8 +1235,8 @@ opt_propagate_moves ()
+ /* got a fixup for all jump_outs? */
+ if (fixups.size () == jump_out.size ())
+ {
+- rtx_insn * before = insns[current_label_index - 1];
+- rtx_insn * after = insns[index + 1];
++ rtx_insn * before = infos[current_label_index - 1].get_insn ();
++ rtx_insn * after = infos[index + 1].get_insn ();
+ rtx bset = single_set (before);
+
+ log ("propagate_moves condition met, moving regs %s, %s\n",
+@@ -1250,7 +1281,7 @@ opt_propagate_moves ()
+ {
+ rtx neu = gen_rtx_SET(
+ dstj, gen_rtx_PLUS(Pmode, dsti, gen_rtx_CONST_INT(Pmode, fixups[k])));
+- rtx_insn * neui = emit_insn_after (neu, jump_out[k]);
++ emit_insn_after (neu, jump_out[k]);
+ }
+ }
+ ++change_count;
+@@ -1290,9 +1321,9 @@ opt_strcpy ()
+ rtx_insn * reg2x;
+ unsigned int regno;
+
+- for (unsigned index = 0; index < insns.size (); ++index)
++ for (unsigned index = 0; index < infos.size (); ++index)
+ {
+- rtx_insn * insn = insns[index];
++ rtx_insn * insn = infos[index].get_insn ();
+
+ if (!NONJUMP_INSN_P(insn))
+ {
+@@ -1411,9 +1442,9 @@ opt_commute_add_move (void)
+ {
+ unsigned change_count = 0;
+
+- for (unsigned index = 0; index + 1 < insns.size (); ++index)
++ for (unsigned index = 0; index + 1 < infos.size (); ++index)
+ {
+- rtx_insn * insn = insns[index];
++ rtx_insn * insn = infos[index].get_insn ();
+ rtx set = single_set (insn);
+ if (!set)
+ continue;
+@@ -1434,7 +1465,7 @@ opt_commute_add_move (void)
+ if (!CONST_INT_P(cnst))
+ continue;
+
+- rtx_insn * next = insns[index + 1];
++ rtx_insn * next = infos[index + 1].get_insn ();
+ rtx set2 = single_set (next);
+ if (!set2)
+ continue;
+@@ -1498,9 +1529,9 @@ opt_const_cmp_to_sub (void)
+ {
+ unsigned change_count = 0;
+ #if HAVE_cc0
+- for (int index = insns.size () - 2; index > 0; --index)
++ for (int index = infos.size () - 2; index > 0; --index)
+ {
+- rtx_insn * insn = insns[index];
++ rtx_insn * insn = infos[index].get_insn ();
+ rtx seti = single_set (insn);
+ if (!seti)
+ continue;
+@@ -1529,7 +1560,7 @@ opt_const_cmp_to_sub (void)
+ continue;
+
+ // maybe add a search?
+- rtx_insn * prev = insns[index - 1];
++ rtx_insn * prev = infos[index - 1].get_insn ();
+ rtx setp = single_set (prev);
+ if (!setp)
+ continue;
+@@ -1564,7 +1595,7 @@ opt_const_cmp_to_sub (void)
+ // invert all conditions using this statement.
+ std::vector<unsigned> todo;
+ std::vector<unsigned> done;
+- done.resize (insns.size ());
++ done.resize (infos.size ());
+ todo.push_back (index + 1);
+
+ while (ok && todo.size ())
+@@ -1583,7 +1614,7 @@ opt_const_cmp_to_sub (void)
+ if (pos + 1 < infos.size ())
+ todo.push_back (pos + 1);
+
+- rtx_insn * patchme = insns[pos];
++ rtx_insn * patchme = infos[pos].get_insn ();
+ if (!JUMP_P(patchme))
+ continue;
+
+@@ -1642,9 +1673,9 @@ static unsigned
+ opt_elim_dead_assign (void)
+ {
+ unsigned change_count = 0;
+- for (int index = insns.size () - 1; index >= 0; --index)
++ for (int index = infos.size () - 1; index >= 0; --index)
+ {
+- rtx_insn * insn = insns[index];
++ rtx_insn * insn = infos[index].get_insn ();
+ if (!NONJUMP_INSN_P(insn))
+ continue;
+
+@@ -1681,11 +1712,11 @@ static unsigned
+ opt_merge_add (void)
+ {
+ unsigned change_count = 0;
+- for (unsigned index = 0; index + 2 < insns.size (); ++index)
++ for (unsigned index = 0; index + 2 < infos.size (); ++index)
+ {
+- rtx_insn * ins1 = insns[index];
+- rtx_insn * ins2 = insns[index + 1];
+- rtx_insn * ins3 = insns[index + 2];
++ rtx_insn * ins1 = infos[index].get_insn ();
++ rtx_insn * ins2 = infos[index + 1].get_insn ();
++ rtx_insn * ins3 = infos[index + 2].get_insn ();
+ if (!NONJUMP_INSN_P(ins1) && !NONJUMP_INSN_P(ins2) && !NONJUMP_INSN_P(ins3))
+ continue;
+
+@@ -1738,17 +1769,6 @@ opt_merge_add (void)
+ return change_count;
+ }
+
+-/*
+- * Move the insns back from temp to insns.
+- */
+-static void
+-clear_temp ()
+-{
+- for (unsigned i = 0; i < temp.size (); ++i)
+- if (temp[i])
+- insns[i] = temp[i], temp[i] = 0;
+-}
+-
+ /**
+ * 1. scan for all used registers.
+ * 2. scan the stack from for omittable push/pop
+@@ -1775,14 +1795,13 @@ static unsigned
+ opt_shrink_stack_frame (void)
+ {
+ /* nothing to do. */
+- if (!insns.size ())
++ if (!infos.size ())
+ return 0;
+
+ std::vector<int> a5pos;
+- temp.resize (insns.size ());
+
+ unsigned pos = 0;
+- rtx_insn * insn = insns[pos];
++ rtx_insn * insn = infos[pos].get_insn ();
+ if (JUMP_P(insn)) /* return -> empty function*/
+ return 0;
+
+@@ -1794,11 +1813,12 @@ opt_shrink_stack_frame (void)
+ * Move prologue to temp.
+ * Only register push and parallel insn unless its a link a5 are moved.
+ */
+- for (; pos < insns.size ();)
++ for (; pos < infos.size ();)
+ {
+- insn = insns[pos];
++ insn_info & ii = infos[pos];
++ insn = ii.get_insn ();
+
+- if (proepilogue[pos] != 1)
++ if (ii.in_proepi () != 1)
+ break;
+
+ rtx pattern = PATTERN (insn);
+@@ -1817,8 +1837,7 @@ opt_shrink_stack_frame (void)
+ else
+ {
+ /* use movem */
+- temp[pos] = insn;
+- insns[pos] = 0;
++ ii.mark_stack ();
+ }
+ ++pos;
+ continue;
+@@ -1845,8 +1864,7 @@ opt_shrink_stack_frame (void)
+ rtx reg = XEXP(predec, 0);
+ if (REG_P(reg) && REGNO(reg) == STACK_POINTER_REGNUM)
+ {
+- temp[pos] = insn;
+- insns[pos] = 0;
++ ii.mark_stack ();
+ }
+ }
+ }
+@@ -1860,9 +1878,8 @@ opt_shrink_stack_frame (void)
+ paramstart -= INTVAL(cx);
+ }
+
+- if (++pos >= insns.size ())
++ if (++pos >= infos.size ())
+ {
+- clear_temp ();
+ return 0;
+ }
+ }
+@@ -1873,20 +1890,21 @@ opt_shrink_stack_frame (void)
+ unsigned prologueend = pos;
+
+ /* search epilogues - there can be multiple epilogues. */
+- while (pos < insns.size ())
++ while (pos < infos.size ())
+ {
+- while (pos < insns.size ())
++ while (pos < infos.size ())
+ {
+- if (proepilogue[pos])
++ if (infos[pos].in_proepi ())
+ break;
+ ++pos;
+ }
+
+ /* move epilogues away. */
+- for (; pos < insns.size (); ++pos)
++ for (; pos < infos.size (); ++pos)
+ {
+- insn = insns[pos];
+- if (JUMP_P(insn) || LABEL_P(insn) || !proepilogue[pos])
++ insn_info & ii = infos[pos];
++ insn = ii.get_insn ();
++ if (JUMP_P(insn) || LABEL_P(insn) || !ii.in_proepi ())
+ break;
+
+ /* omit the frame pointer a5. */
+@@ -1903,8 +1921,7 @@ opt_shrink_stack_frame (void)
+ }
+
+ /* movem. */
+- temp[pos] = insn;
+- insns[pos] = 0;
++ ii.mark_stack ();
+ }
+ else if (GET_CODE(pattern) == SET)
+ {
+@@ -1920,10 +1937,7 @@ opt_shrink_stack_frame (void)
+ {
+ rtx reg = XEXP(postinc, 0);
+ if (REG_P(reg) && REGNO(reg) == STACK_POINTER_REGNUM)
+- {
+- temp[pos] = insn;
+- insns[pos] = 0;
+- }
++ ii.mark_stack ();
+ }
+ }
+ }
+@@ -1936,10 +1950,10 @@ opt_shrink_stack_frame (void)
+ insn_info ii;
+ for (unsigned i = 0; i < infos.size (); ++i)
+ {
+- if (proepilogue[i])
++ insn_info & jj = infos[i];
++ if (jj.is_stack ())
+ continue;
+
+- insn_info & jj = infos[i];
+ ii.merge (jj);
+ }
+ unsigned freemask = ~ii.get_use ();
+@@ -1949,12 +1963,13 @@ opt_shrink_stack_frame (void)
+
+ unsigned adjust = 0;
+ /* now all push/pop insns are in temp. */
+- for (unsigned i = 0; i < temp.size (); ++i)
++ for (unsigned i = 0; i < infos.size (); ++i)
+ {
+- insn = temp[i];
+- if (!insn)
++ insn_info & ii = infos[i];
++ if (!ii.is_stack ())
+ continue;
+
++ insn = ii.get_insn ();
+ rtx pattern = PATTERN (insn);
+ /* check the pushed regs, either a vector or single statements */
+ if (GET_CODE(pattern) == PARALLEL)
+@@ -2119,9 +2134,10 @@ opt_shrink_stack_frame (void)
+ /* fix sp offsets. */
+ if (!usea5 && adjust)
+ {
+- for (unsigned index = 0; index < insns.size (); ++index)
++ for (unsigned index = 0; index < infos.size (); ++index)
+ {
+- insn = insns[index];
++ insn_info & ii = infos[index];
++ insn = ii.get_insn ();
+ if (!insn || !INSN_P(insn))
+ continue;
+
+@@ -2155,17 +2171,16 @@ opt_shrink_stack_frame (void)
+ {
+ for (std::vector<int>::iterator i = a5pos.begin (); i != a5pos.end (); ++i)
+ {
+- temp[*i] = insns[*i];
+- insns[*i] = 0;
++ insn_info & ii = infos[*i];
++ ii.mark_stack ();
+ }
+- update_insn_infos ();
+- insn_info ii;
+ for (unsigned i = 0; i < infos.size (); ++i)
+ {
+- if (proepilogue[i])
++ insn_info ii;
++ insn_info & jj = infos[i];
++ if (jj.is_stack ())
+ continue;
+
+- insn_info & jj = infos[i];
+ ii.merge (jj);
+ }
+ unsigned freemask = ~ii.get_use ();
+@@ -2174,13 +2189,10 @@ opt_shrink_stack_frame (void)
+ {
+ log ("dropping unused frame pointer\n");
+ for (std::vector<int>::iterator i = a5pos.begin (); i != a5pos.end (); ++i)
+- SET_INSN_DELETED(temp[*i]);
++ SET_INSN_DELETED(infos[*i].get_insn ());
+ }
+ }
+
+- /* restore stack insns */
+- clear_temp ();
+-
+ return 0;
+ }
+
+
+From a882cc15bab5a29c566ccda41663549d87cb0be3 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 28 Apr 2017 11:39:49 +0200
+Subject: [PATCH 099/303] @R optimize opt_merge_add
+
+---
+ gcc/bbb-opts.c | 370 ++++++++++++++++++++++++++++++++++++++++++++-------------
+ 1 file changed, 287 insertions(+), 83 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index fc4acc87a0a9..99c41128e5b8 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -122,22 +122,114 @@ log (char const * fmt, ...)
+ class insn_info
+ {
+ rtx_insn * insn; // the insn
++
++ // usage flags
+ unsigned myuse; // bit set if registers are used in this statement
+ unsigned hard; // bit set if registers can't be renamed
+ unsigned use; // bit set if registers are used in program flow
+ unsigned def; // bit set if registers are defined here
++
+ int proepi; // 1 = in prologue, 2 = in epilogue, 0 = other
++
+ bool stack; // part of stack frame insns
+
++ // stuff to analyze insns
++ bool label;
++ bool jump;
++ bool call;
++ bool compare;
++ bool dst_reg;
++ bool src_reg;
++ bool dst_mem;
++ bool src_mem;
++ bool dst_plus;
++ bool src_plus;
++ bool src_const;
++
++ int dst_regno;
++ int dst_mem_reg;
++ unsigned dst_mem_addr;
++
++ int src_regno;
++ int src_mem_regno;
++ unsigned src_intval;
++
+ insn_info &
+ operator = (insn_info const &);
+
+ public:
+ insn_info (rtx_insn * i = 0, int p = 0) :
+- insn (i), myuse (0), hard (0), use (0), def (0), proepi (p), stack (false)
++ insn (i), myuse (0), hard (0), use (0), def (0), proepi (p), stack (false), label (false), jump (false), call (
++ false), compare (false), dst_reg (false), src_reg (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus (
++ false), src_const (false), dst_regno (-1), dst_mem_reg (-1), dst_mem_addr (0), src_regno (-1), src_mem_regno (
++ -1), src_intval (0)
++ {
++ }
++
++ inline void
++ plus_to_move (rtx_insn * newinsn)
++ {
++ insn = newinsn;
++ dst_plus = false;
++ dst_reg = true;
++ // usage flags did not change
++ }
++
++ inline bool
++ is_dst_reg () const
++ {
++ return dst_reg;
++ }
++
++ inline bool
++ is_src_reg () const
++ {
++ return src_reg;
++ }
++
++ inline int
++ get_dst_regno () const
++ {
++ return dst_regno;
++ }
++
++ inline int
++ get_src_regno () const
++ {
++ return src_regno;
++ }
++
++ inline bool
++ is_src_plus () const
++ {
++ return src_plus;
++ }
++
++ inline bool
++ is_src_const () const
+ {
++ return src_const;
+ }
+
++ inline void
++ mark_jump ()
++ {
++ jump = true;
++ }
++ inline void
++ mark_call ()
++ {
++ call = true;
++ }
++ inline void
++ mark_label ()
++ {
++ label = true;
++ }
++
++ void
++ fledder (rtx set);
++
+ /* update usage. */
+ void
+ update (insn_info & o)
+@@ -470,6 +562,101 @@ insn_info::scan_rtx (rtx x)
+ }
+ }
+
++/* read the set and grab infos */
++void
++insn_info::fledder (rtx set)
++{
++ rtx dst = SET_DEST(set);
++ rtx src = SET_SRC(set);
++
++ if (dst == cc0_rtx)
++ {
++ compare = true;
++ set = src;
++ dst = SET_DEST(set);
++ src = SET_SRC(set);
++ }
++
++ if (REG_P(dst))
++ {
++ dst_reg = true;
++ dst_regno = REGNO(dst);
++ }
++ else if (MEM_P(dst))
++ {
++ dst_mem = true;
++ rtx mem = XEXP(dst, 0);
++ if (REG_P(mem))
++ dst_mem_reg = REGNO(mem);
++ else if (GET_CODE(mem) == CONST_INT)
++ dst_mem_addr = INTVAL(mem);
++ else if (GET_CODE(mem) == PLUS)
++ {
++ dst_plus = true;
++ rtx reg = XEXP(mem, 0);
++ rtx konst = XEXP(mem, 1);
++ if (REG_P(reg) && GET_CODE(konst) == CONST_INT)
++ {
++ dst_mem_reg = REGNO(reg);
++ dst_mem_addr = INTVAL(konst);
++ }
++ }
++ }
++
++ if (REG_P(src))
++ {
++ src_reg = true;
++ src_regno = REGNO(src);
++ }
++ else if (MEM_P(src))
++ {
++ src_mem = true;
++ rtx mem = XEXP(src, 0);
++ if (REG_P(mem))
++ src_mem_regno = REGNO(mem);
++ else if (GET_CODE(mem) == CONST_INT)
++ src_intval = INTVAL(mem);
++ else if (GET_CODE(mem) == PLUS)
++ {
++ src_plus = true;
++ rtx reg = XEXP(mem, 0);
++ rtx konst = XEXP(mem, 1);
++ if (REG_P(reg) && GET_CODE(konst) == CONST_INT)
++ {
++ src_mem_regno = REGNO(reg);
++ src_const = true;
++ src_intval = INTVAL(konst);
++ }
++ }
++ }
++ else if (GET_CODE(src) == CONST_INT)
++ {
++ src_const = true;
++ src_intval = INTVAL(src);
++ }
++ else if (GET_CODE(src) == PLUS)
++ {
++ src_plus = true;
++ rtx reg = XEXP(src, 0);
++ rtx konst = XEXP(src, 1);
++ if (REG_P(reg))
++ {
++ if (GET_CODE(konst) == CONST_INT)
++ {
++ src_regno = REGNO(reg);
++ src_const = true;
++ src_intval = INTVAL(konst);
++ }
++ else if (REG_P(konst))
++ {
++ src_reg = true;
++ src_regno = REGNO(konst);
++ }
++ }
++ }
++
++}
++
+ /* create a copy for a reg. Optional specify a new register number. */
+ static rtx
+ copy_reg (rtx reg, int newregno)
+@@ -600,6 +787,9 @@ append_reg_usage (FILE * f, rtx_insn * insn)
+ if (ii.is_use (FIRST_PSEUDO_REGISTER))
+ fprintf (f, ii.is_def (FIRST_PSEUDO_REGISTER) ? "+cc " : " cc ");
+
++ if (f == stderr)
++ fprintf (f, "\n");
++
+ }
+
+ /*
+@@ -635,43 +825,6 @@ dump_insns (char const * name, bool all)
+ }
+ }
+
+-/*
+- * Create a filtered view of insns - keep only those to work with.
+- */
+-static void
+-update_insns ()
+-{
+- rtx_insn *insn, *next;
+- clear ();
+-
+- char inproepilogue = 1;
+- /* create a vector with relevant insn. */
+- for (insn = get_insns (); insn; insn = next)
+- {
+- next = NEXT_INSN (insn);
+-
+- if (NONJUMP_INSN_P (insn) || LABEL_P(insn) || JUMP_P(insn) || CALL_P(insn))
+- {
+- if (JUMP_P(insn))
+- jumps.push_back (insn);
+-
+- insn2index.insert (std::make_pair (insn, infos.size ()));
+- infos.push_back (insn_info (insn, inproepilogue));
+-
+- if (JUMP_P(insn))
+- inproepilogue = 0;
+- }
+-
+- if (NOTE_P(insn))
+- {
+- if (NOTE_KIND(insn) == NOTE_INSN_PROLOGUE_END)
+- inproepilogue = 0;
+- else if (NOTE_KIND(insn) == NOTE_INSN_EPILOGUE_BEG)
+- inproepilogue = 2;
+- }
+- }
+-}
+-
+ /* This is the important function to track register usage plus hard/live state.
+ *
+ * Start at bottom and work upwards. On all labels trigger all jumps referring to this label.
+@@ -764,6 +917,62 @@ update_insn_infos (void)
+ }
+ }
+
++/*
++ * Create a filtered view of insns - keep only those to work with.
++ */
++static void
++update_insns ()
++{
++ rtx_insn *insn, *next;
++ clear ();
++
++ char inproepilogue = 1;
++ /* create a vector with relevant insn. */
++ for (insn = get_insns (); insn; insn = next)
++ {
++ next = NEXT_INSN (insn);
++
++ if (NONJUMP_INSN_P (insn) || LABEL_P(insn) || JUMP_P(insn) || CALL_P(insn))
++ {
++
++ insn2index.insert (std::make_pair (insn, infos.size ()));
++ infos.push_back (insn_info (insn, inproepilogue));
++ insn_info & ii = infos[infos.size () - 1];
++
++ if (JUMP_P(insn))
++ {
++ jumps.push_back (insn);
++ inproepilogue = 0;
++
++ ii.mark_jump ();
++ }
++ else if (LABEL_P(insn))
++ {
++ ii.mark_label ();
++ }
++ else if (CALL_P(insn))
++ {
++ ii.mark_call ();
++ }
++ else
++ {
++ rtx set = single_set (insn);
++ if (set)
++ ii.fledder (set);
++ }
++ }
++
++ if (NOTE_P(insn))
++ {
++ if (NOTE_KIND(insn) == NOTE_INSN_PROLOGUE_END)
++ inproepilogue = 0;
++ else if (NOTE_KIND(insn) == NOTE_INSN_EPILOGUE_BEG)
++ inproepilogue = 2;
++ }
++ }
++ update_insn_infos ();
++}
++
+ /* convert the lowest set bit into a register number. */
+ static int
+ bit2regno (unsigned bit)
+@@ -1714,57 +1923,57 @@ opt_merge_add (void)
+ unsigned change_count = 0;
+ for (unsigned index = 0; index + 2 < infos.size (); ++index)
+ {
+- rtx_insn * ins1 = infos[index].get_insn ();
+- rtx_insn * ins2 = infos[index + 1].get_insn ();
+- rtx_insn * ins3 = infos[index + 2].get_insn ();
+- if (!NONJUMP_INSN_P(ins1) && !NONJUMP_INSN_P(ins2) && !NONJUMP_INSN_P(ins3))
+- continue;
++ insn_info & ii0 = infos[index];
++ insn_info & ii1 = infos[index + 1];
++ insn_info & ii2 = infos[index + 2];
+
+- rtx set1 = single_set (ins1);
+- rtx set2 = single_set (ins2);
+- rtx set3 = single_set (ins3);
+- if (!set1 || !set2 || !set3)
+- continue;
++ if (!ii2.is_dst_reg ())
++ {
++ index += 2;
++ continue;
++ }
++
++ if (!ii1.is_dst_reg ())
++ {
++ ++index;
++ continue;
++ }
+
+- rtx dst1 = SET_DEST(set1);
+- rtx dst2 = SET_DEST(set2);
+- rtx dst3 = SET_DEST(set3);
+- if (!REG_P(dst1) || !REG_P(dst2) || !REG_P(dst3))
++ if (!ii0.is_dst_reg () || !ii0.is_src_plus () || !ii1.is_src_plus () || !ii2.is_src_plus ())
+ continue;
+
+- CC_STATUS_INIT;
+- NOTICE_UPDATE_CC(PATTERN (ins2), ins2);
+- if (cc_status.value1 || cc_status.value2)
++ if (!ii0.is_src_const () || !ii1.is_src_reg () || !ii2.is_src_const ())
+ continue;
+
+- rtx src1 = SET_SRC(set1);
+- rtx src2 = SET_SRC(set2);
+- rtx src3 = SET_SRC(set3);
+- if (GET_CODE(src1) != PLUS || GET_CODE(src2) != PLUS || GET_CODE(src3) != PLUS)
++ if (ii0.get_dst_regno () != ii1.get_dst_regno () || ii1.get_src_regno () != ii2.get_dst_regno ())
+ continue;
+
+- rtx l1 = XEXP(src1, 0);
+-// rtx l2 = XEXP(src2, 0);
+-// rtx l3 = XEXP(src3, 0);
++ rtx_insn * insn1 = ii1.get_insn ();
+
+- rtx r1 = XEXP(src1, 1);
+- rtx r2 = XEXP(src2, 1);
+- rtx r3 = XEXP(src3, 1);
+- if (!CONST_INT_P(r1) || !REG_P(r2) || !CONST_INT_P(r3))
++ CC_STATUS_INIT;
++ NOTICE_UPDATE_CC(PATTERN (insn1), insn1);
++ if (cc_status.value1 || cc_status.value2)
+ continue;
+
+- if (REGNO(dst1) != REGNO(dst2) || REGNO(r2) != REGNO(dst3))
+- continue;
++ log ("%d: merge_add applied\n", index);
++
++ rtx_insn * insn0 = ii0.get_insn ();
++ rtx set = PATTERN (insn0);
+
+- log ("merge_add applied\n");
++ // convert lea (-1,a0),a1 into move.l a0,a1
++ rtx_insn * newins0 = make_insn_raw (gen_rtx_SET(XEXP(set, 0), XEXP(XEXP(set, 1), 0)));
++ add_insn_after (newins0, insn0, 0);
++ SET_INSN_DELETED(insn0);
++ // update infos accordingly
++ ii0.plus_to_move (newins0);
+
+- rtx_insn * newins1 = make_insn_raw (gen_rtx_SET(dst1, l1));
+- add_insn_after (newins1, ins1, 0);
+- SET_INSN_DELETED(ins1);
++ rtx_insn * insn2 = ii2.get_insn ();
++ rtx_insn * newins1 = make_insn_raw (PATTERN (insn1));
++ add_insn_after (newins1, insn2, 0);
++ SET_INSN_DELETED(insn1);
++// ii1.swap_adds(newins1, ii2);
+
+- rtx_insn * newins2 = make_insn_raw (PATTERN (ins2));
+- add_insn_after (newins2, ins3, 0);
+- SET_INSN_DELETED(ins2);
++ ++change_count;
+ }
+ return change_count;
+ }
+@@ -1946,7 +2155,6 @@ opt_shrink_stack_frame (void)
+ ++pos;
+ }
+ /* gather usage stats without prologue/epilogue */
+- update_insn_infos ();
+ insn_info ii;
+ for (unsigned i = 0; i < infos.size (); ++i)
+ {
+@@ -2270,7 +2478,6 @@ namespace
+ {
+ int done = 1;
+ update_insns ();
+- update_insn_infos ();
+ if (do_opt_strcpy && opt_strcpy ())
+ done = 0, update_insns ();
+
+@@ -2280,22 +2487,20 @@ namespace
+ if (do_propagate_moves && opt_propagate_moves ())
+ done = 0, update_insns ();
+
+- update_insn_infos ();
+ if (do_const_cmp_to_sub && opt_const_cmp_to_sub ())
+- done = 0, update_insns (), update_insn_infos ();
++ done = 0, update_insns ();
+
+ if (do_merge_add && opt_merge_add ())
+- done = 0, update_insns (), update_insn_infos ();
++ done = 0, update_insns ();
+
+ if (do_elim_dead_assign && opt_elim_dead_assign ())
+- done = 0, update_insns (), update_insn_infos ();
++ done = 0, update_insns ();
+
+ if (do_bb_reg_rename)
+ {
+ while (opt_reg_rename ())
+ {
+ update_insns ();
+- update_insn_infos ();
+ done = 0;
+ }
+ }
+@@ -2308,7 +2513,6 @@ namespace
+ {
+ opt_shrink_stack_frame ();
+ update_insns ();
+- update_insn_infos ();
+ }
+
+ if (strchr (string_bbb_opts, 'X') || strchr (string_bbb_opts, 'x'))
+
+From c7349bb3c9644ea0ceb0f82b8e739df734db9317 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 28 Apr 2017 13:32:51 +0200
+Subject: [PATCH 100/303] @R optimize opt_merge_add - no need to run
+ update_insns afterwards
+
+---
+ gcc/bbb-opts.c | 108 ++++++++++++++++++++++++++++++++++++++++++++-------------
+ 1 file changed, 84 insertions(+), 24 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 99c41128e5b8..9d40a534dc1a 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -154,9 +154,6 @@ class insn_info
+ int src_mem_regno;
+ unsigned src_intval;
+
+- insn_info &
+- operator = (insn_info const &);
+-
+ public:
+ insn_info (rtx_insn * i = 0, int p = 0) :
+ insn (i), myuse (0), hard (0), use (0), def (0), proepi (p), stack (false), label (false), jump (false), call (
+@@ -166,14 +163,14 @@ class insn_info
+ {
+ }
+
+- inline void
+- plus_to_move (rtx_insn * newinsn)
+- {
+- insn = newinsn;
+- dst_plus = false;
+- dst_reg = true;
+- // usage flags did not change
+- }
++ int
++ get_index () const;
++
++ void
++ plus_to_move (rtx_insn * newinsn);
++
++ void
++ swap_adds(rtx_insn * newinsn, insn_info & ii);
+
+ inline bool
+ is_dst_reg () const
+@@ -715,7 +712,69 @@ temp_reg_rename (std::vector<std::pair<rtx *, rtx> > & loc, rtx x, unsigned oldr
+ */
+ static std::vector<insn_info> infos;
+ static std::vector<rtx_insn *> jumps;
+-static std::map<rtx_insn *, unsigned> insn2index;
++static std::map<rtx_insn *, insn_info *> insn2index;
++
++static insn_info * info0;
++
++static void
++update_insn2index ()
++{
++ infos.reserve (infos.size () * 8 / 7 + 2);
++ insn2index.clear ();
++ /* needs a separate pass since the insn_infos require fixed addresses for ->get_index() */
++ for (unsigned i = 0; i < infos.size (); ++i)
++ {
++ insn_info & ii = infos[i];
++ insn2index.insert (std::make_pair (ii.get_insn (), &ii));
++ }
++ info0 = &infos[0];
++}
++
++int
++insn_info::get_index () const
++{
++ insn_info * ii = &infos[0];
++
++ if (ii == info0)
++ {
++ ptrdiff_t diff = ((char const *) this - (char const *) ii);
++ unsigned pos = diff / sizeof(insn_info);
++ if (pos < infos.size ())
++ return pos;
++ }
++
++ // realloc happened...
++ for (unsigned i = 0; i < infos.size (); ++i)
++ if (infos[i].get_insn () == this->insn)
++ return i;
++
++ // whoops!?
++ return 0;
++}
++
++void
++insn_info::plus_to_move (rtx_insn * newinsn)
++{
++ insn = newinsn;
++ src_plus = false;
++ src_reg = true;
++ insn2index.insert(std::make_pair(insn, this));
++ // usage flags did not change
++}
++
++void
++insn_info::swap_adds(rtx_insn * newinsn, insn_info & ii)
++{
++ insn = newinsn;
++
++ std::swap(*this, ii);
++
++ insn2index.insert(std::make_pair(insn, this));
++ insn2index.insert(std::make_pair(ii.insn, &ii));
++
++ // usage flags did not change
++}
++
+
+ /*
+ * Reset collected data.
+@@ -759,7 +818,7 @@ append_reg_usage (FILE * f, rtx_insn * insn)
+ if (i == insn2index.end ())
+ return;
+
+- insn_info & ii = infos[i->second];
++ insn_info & ii = *i->second;
+
+ if (f != stderr)
+ fprintf (f, "\n\t\t\t\t\t\t| ");
+@@ -867,9 +926,9 @@ update_insn_infos (void)
+ {
+ if (JUMP_LABEL(*i) == insn)
+ {
+- std::map<rtx_insn *, unsigned>::iterator j = insn2index.find (*i);
++ auto j = insn2index.find (*i);
+ if (j != insn2index.end ())
+- todo.push_back (std::make_pair (j->second, ii));
++ todo.push_back (std::make_pair (j->second->get_index (), ii));
+ }
+ }
+ continue;
+@@ -935,7 +994,6 @@ update_insns ()
+ if (NONJUMP_INSN_P (insn) || LABEL_P(insn) || JUMP_P(insn) || CALL_P(insn))
+ {
+
+- insn2index.insert (std::make_pair (insn, infos.size ()));
+ infos.push_back (insn_info (insn, inproepilogue));
+ insn_info & ii = infos[infos.size () - 1];
+
+@@ -970,6 +1028,8 @@ update_insns ()
+ inproepilogue = 2;
+ }
+ }
++
++ update_insn2index ();
+ update_insn_infos ();
+ }
+
+@@ -1088,11 +1148,11 @@ opt_reg_rename (void)
+ {
+ if (JUMP_LABEL(*i) == insn)
+ {
+- std::map<rtx_insn *, unsigned>::iterator j = insn2index.find (*i);
++ auto j = insn2index.find (*i);
+ if (j == insn2index.end ())
+ continue;
+
+- unsigned start = j->second;
++ unsigned start = j->second->get_index ();
+ if (!infos[start].is_use (rename_regno))
+ continue;
+
+@@ -1131,7 +1191,7 @@ opt_reg_rename (void)
+ /* follow jump and/or next insn. */
+ if (JUMP_P(insn))
+ {
+- std::map<rtx_insn *, unsigned>::iterator j = insn2index.find ((rtx_insn *) JUMP_LABEL(insn));
++ auto j = insn2index.find ((rtx_insn *) JUMP_LABEL(insn));
+ if (j == insn2index.end ())
+ {
+ /* whoops - label not found. */
+@@ -1139,7 +1199,7 @@ opt_reg_rename (void)
+ break;
+ }
+
+- unsigned label_index = j->second;
++ unsigned label_index = j->second->get_index ();
+ if (found.find (label_index) == found.end ())
+ {
+ /* if the rename_reg is used in the insn before.
+@@ -1827,9 +1887,9 @@ opt_const_cmp_to_sub (void)
+ if (!JUMP_P(patchme))
+ continue;
+
+- std::map<rtx_insn *, unsigned>::iterator j = insn2index.find ((rtx_insn *) JUMP_LABEL(patchme));
++ auto j = insn2index.find ((rtx_insn *) JUMP_LABEL(patchme));
+ if (j != insn2index.end ())
+- todo.push_back (j->second);
++ todo.push_back (j->second->get_index ());
+
+ rtx jmppattern = PATTERN (patchme);
+
+@@ -1971,7 +2031,7 @@ opt_merge_add (void)
+ rtx_insn * newins1 = make_insn_raw (PATTERN (insn1));
+ add_insn_after (newins1, insn2, 0);
+ SET_INSN_DELETED(insn1);
+-// ii1.swap_adds(newins1, ii2);
++ ii1.swap_adds(newins1, ii2);
+
+ ++change_count;
+ }
+@@ -2491,7 +2551,7 @@ namespace
+ done = 0, update_insns ();
+
+ if (do_merge_add && opt_merge_add ())
+- done = 0, update_insns ();
++ done = 0;
+
+ if (do_elim_dead_assign && opt_elim_dead_assign ())
+ done = 0, update_insns ();
+
+From 6bfa56b92ce1a9b99b72ef18b7ba14d71542ef8e Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 28 Apr 2017 17:45:15 +0200
+Subject: [PATCH 101/303] @N add opt_immediate
+
+---
+ gcc/bbb-opts.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 163 insertions(+), 11 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 9d40a534dc1a..aa841f737cf8 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -170,7 +170,10 @@ class insn_info
+ plus_to_move (rtx_insn * newinsn);
+
+ void
+- swap_adds(rtx_insn * newinsn, insn_info & ii);
++ swap_adds (rtx_insn * newinsn, insn_info & ii);
++
++ void
++ immediate2base (unsigned regno, unsigned base);
+
+ inline bool
+ is_dst_reg () const
+@@ -178,6 +181,48 @@ class insn_info
+ return dst_reg;
+ }
+
++ inline bool
++ is_dst_mem () const
++ {
++ return dst_mem;
++ }
++
++ inline bool
++ has_dst_memreg () const
++ {
++ return dst_mem_reg >= 0;
++ }
++
++ inline bool
++ has_dst_addr () const
++ {
++ return dst_mem_addr != 0;
++ }
++
++ inline bool
++ is_label () const
++ {
++ return label;
++ }
++
++ inline bool
++ is_jump () const
++ {
++ return jump;
++ }
++
++ inline bool
++ is_call () const
++ {
++ return call;
++ }
++
++ inline unsigned
++ get_dst_addr () const
++ {
++ return dst_mem_addr;
++ }
++
+ inline bool
+ is_src_reg () const
+ {
+@@ -447,7 +492,7 @@ class insn_info
+ if (def & hard)
+ return 0;
+
+- if (!def || def > 0x1000)
++ if (!def || (def & ~(1 << FIRST_PSEUDO_REGISTER)) > 0x1000)
+ return 0;
+
+ unsigned mask = def - 1;
+@@ -758,24 +803,53 @@ insn_info::plus_to_move (rtx_insn * newinsn)
+ insn = newinsn;
+ src_plus = false;
+ src_reg = true;
+- insn2index.insert(std::make_pair(insn, this));
++ insn2index.insert (std::make_pair (insn, this));
+ // usage flags did not change
+ }
+
+ void
+-insn_info::swap_adds(rtx_insn * newinsn, insn_info & ii)
++insn_info::swap_adds (rtx_insn * newinsn, insn_info & ii)
+ {
+ insn = newinsn;
+
+- std::swap(*this, ii);
++ std::swap (*this, ii);
+
+- insn2index.insert(std::make_pair(insn, this));
+- insn2index.insert(std::make_pair(ii.insn, &ii));
++ insn2index.insert (std::make_pair (insn, this));
++ insn2index.insert (std::make_pair (ii.insn, &ii));
+
+ // usage flags did not change
+ }
+
++void
++insn_info::immediate2base (unsigned regno, unsigned base)
++{
++ rtx set = PATTERN (get_insn ());
++ rtx src = SET_SRC(set);
++ machine_mode mode = GET_MODE(SET_DEST(set));
++
++ unsigned addr = get_dst_addr ();
++ unsigned offset = addr - base;
++
++ rtx pattern;
++ if (base == addr)
++ pattern = gen_rtx_SET(gen_rtx_MEM (mode, gen_raw_REG (SImode, regno)), SET_SRC(set));
++ else
++ pattern = gen_rtx_SET(
++ gen_rtx_MEM (mode, gen_rtx_PLUS(SImode, gen_raw_REG (SImode, regno), gen_rtx_CONST_INT(SImode, offset))),
++ SET_SRC(set));
++
++ SET_INSN_DELETED(insn);
++ insn = emit_insn_after (pattern, insn);
++
++ mark_use (regno);
++
++ dst_mem_reg = regno;
++ dst_mem = true;
++ dst_mem_addr = offset;
++ dst_plus = offset != 0;
+
++ insn2index.insert (std::make_pair (insn, this));
++}
+ /*
+ * Reset collected data.
+ */
+@@ -1987,19 +2061,19 @@ opt_merge_add (void)
+ insn_info & ii1 = infos[index + 1];
+ insn_info & ii2 = infos[index + 2];
+
+- if (!ii2.is_dst_reg ())
++ if (!ii2.is_dst_reg () || ii2.is_dst_mem ())
+ {
+ index += 2;
+ continue;
+ }
+
+- if (!ii1.is_dst_reg ())
++ if (!ii1.is_dst_reg () || ii1.is_dst_mem ())
+ {
+ ++index;
+ continue;
+ }
+
+- if (!ii0.is_dst_reg () || !ii0.is_src_plus () || !ii1.is_src_plus () || !ii2.is_src_plus ())
++ if (ii0.is_dst_mem () || !ii0.is_dst_reg () || !ii0.is_src_plus () || !ii1.is_src_plus () || !ii2.is_src_plus ())
+ continue;
+
+ if (!ii0.is_src_const () || !ii1.is_src_reg () || !ii2.is_src_const ())
+@@ -2031,7 +2105,7 @@ opt_merge_add (void)
+ rtx_insn * newins1 = make_insn_raw (PATTERN (insn1));
+ add_insn_after (newins1, insn2, 0);
+ SET_INSN_DELETED(insn1);
+- ii1.swap_adds(newins1, ii2);
++ ii1.swap_adds (newins1, ii2);
+
+ ++change_count;
+ }
+@@ -2464,6 +2538,80 @@ opt_shrink_stack_frame (void)
+ return 0;
+ }
+
++static unsigned
++opt_immediate (void)
++{
++ unsigned change_count = 0;
++
++ for (unsigned i = 0; i < infos.size (); ++i)
++ {
++ insn_info & ii = infos[i];
++ if (!ii.is_dst_mem () || !ii.has_dst_addr () || ii.has_dst_memreg())
++ continue;
++
++ unsigned freemask = ~(ii.get_use () | ii.get_def ()) & 0x7f00;
++ if (!freemask)
++ continue;
++
++ std::vector<unsigned> found;
++ found.push_back (i);
++ unsigned base = ii.get_dst_addr ();
++ unsigned j = i + 1;
++ for (; j < infos.size (); ++j)
++ {
++ insn_info & jj = infos[j];
++ if (jj.is_label () || jj.is_jump () || jj.is_call ())
++ break;
++
++ freemask &= ~(jj.get_use () | jj.get_def ());
++ if (!freemask)
++ break;
++
++ if (jj.is_dst_mem () && jj.has_dst_addr () && !jj.has_dst_memreg())
++ {
++ unsigned addr = jj.get_dst_addr ();
++ if (addr < base)
++ base = addr;
++ if (addr - base > 0x7ffc)
++ continue;
++
++ found.push_back (j);
++ }
++ }
++
++ if (freemask && found.size () > 2)
++ {
++ unsigned regno = bit2regno (freemask);
++ log ("modifying %d immediate using %s\n", found.size (), reg_names[regno]);
++
++ for (auto k = found.begin (); k != found.end (); ++k)
++ {
++ insn_info & kk = infos[*k];
++ kk.immediate2base (regno, base);
++ }
++
++ // load base into reg
++ rtx lea = gen_rtx_SET(gen_raw_REG (SImode, regno), gen_rtx_CONST_INT (SImode, base));
++ rtx_insn * insn = emit_insn_before (lea, ii.get_insn ());
++ insn_info nn (insn);
++ nn.scan();
++ nn.fledder (lea);
++ nn.mark_def (regno);
++ infos.insert (infos.begin () + i, nn);
++ while (i++ < j)
++ infos[i].mark_use(regno);
++ ++j;
++ }
++
++ i = j;
++ }
++
++ if (change_count)
++ update_insn2index ();
++
++ return change_count;
++}
++
+ namespace
+ {
+
+@@ -2533,6 +2681,7 @@ namespace
+ bool do_elim_dead_assign = strchr (string_bbb_opts, 'e') || strchr (string_bbb_opts, '+');
+ bool do_bb_reg_rename = strchr (string_bbb_opts, 'r') || strchr (string_bbb_opts, '+');
+ bool do_shrink_stack_frame = strchr (string_bbb_opts, 'f') || strchr (string_bbb_opts, '+');
++ bool do_immediate = strchr (string_bbb_opts, 'i') || strchr (string_bbb_opts, '+');
+
+ for (;;)
+ {
+@@ -2556,6 +2705,9 @@ namespace
+ if (do_elim_dead_assign && opt_elim_dead_assign ())
+ done = 0, update_insns ();
+
++ if (do_immediate && opt_immediate ())
++ done = 0, update_insns ();
++
+ if (do_bb_reg_rename)
+ {
+ while (opt_reg_rename ())
+
+From d851a82657b37cc2fd5f8077fd97c9ea8bef0bfc Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 28 Apr 2017 18:21:19 +0200
+Subject: [PATCH 102/303] @B fix opt_merge_add
+
+---
+ gcc/bbb-opts.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index aa841f737cf8..face11f85f8a 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -187,6 +187,12 @@ class insn_info
+ return dst_mem;
+ }
+
++ inline bool
++ is_src_mem () const
++ {
++ return src_mem;
++ }
++
+ inline bool
+ has_dst_memreg () const
+ {
+@@ -2073,10 +2079,10 @@ opt_merge_add (void)
+ continue;
+ }
+
+- if (ii0.is_dst_mem () || !ii0.is_dst_reg () || !ii0.is_src_plus () || !ii1.is_src_plus () || !ii2.is_src_plus ())
++ if (!ii0.is_dst_reg () || !ii0.is_src_plus () || !ii1.is_src_plus () || !ii2.is_src_plus ())
+ continue;
+
+- if (!ii0.is_src_const () || !ii1.is_src_reg () || !ii2.is_src_const ())
++ if (ii0.is_src_mem () || !ii0.is_src_const () || !ii1.is_src_reg () || ii2.is_src_mem () || !ii2.is_src_const ())
+ continue;
+
+ if (ii0.get_dst_regno () != ii1.get_dst_regno () || ii1.get_src_regno () != ii2.get_dst_regno ())
+
+From 25996bade9f5e8d41f81fac1d07cb82cebe5832c Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 28 Apr 2017 21:55:59 +0200
+Subject: [PATCH 103/303] @B fix opt_immediate: update reg usage
+
+---
+ gcc/bbb-opts.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index face11f85f8a..5683ac21640b 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -358,6 +358,13 @@ class insn_info
+ {
+ return use;
+ }
++
++ inline void
++ set_use(unsigned u)
++ {
++ use = u;
++ }
++
+ inline unsigned
+ get_def () const
+ {
+@@ -1288,7 +1295,7 @@ opt_reg_rename (void)
+ insn_info & bb = infos[label_index + 1];
+ if (bb.is_use (rename_regno))
+ {
+- unsigned start = find_start (found, label_index - 1, rename_regno);
++ unsigned start = find_start (found, label_index, rename_regno);
+ todo.push_back (start);
+ }
+ todo.push_back (label_index + 1);
+@@ -2600,6 +2607,7 @@ opt_immediate (void)
+ rtx lea = gen_rtx_SET(gen_raw_REG (SImode, regno), gen_rtx_CONST_INT (SImode, base));
+ rtx_insn * insn = emit_insn_before (lea, ii.get_insn ());
+ insn_info nn (insn);
++ nn.set_use(ii.get_use());
+ nn.scan();
+ nn.fledder (lea);
+ nn.mark_def (regno);
+
+From 3fdf716d76ad01cdef87f14ebceb8832ca9b32a7 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 28 Apr 2017 23:07:13 +0200
+Subject: [PATCH 104/303] @B fix opt_immediate: update reg usage
+
+---
+ gcc/bbb-opts.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 5683ac21640b..99c49db4238d 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -2615,6 +2615,7 @@ opt_immediate (void)
+ while (i++ < j)
+ infos[i].mark_use(regno);
+ ++j;
++ ++change_count;
+ }
+
+ i = j;
+
+From b68846bfd5192be42bf080d09e429227aebdb7d3 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 30 Apr 2017 18:27:54 +0200
+Subject: [PATCH 105/303] @I cleanup, remove unnecessary changes
+
+---
+ .cproject | 6 +++++-
+ gcc/DATESTAMP | 2 +-
+ gcc/cfgbuild.c | 1 -
+ gcc/config/m68k/amigaos.c | 10 ----------
+ gcc/config/m68k/amigaos.h | 4 ----
+ gcc/doc/tm.texi | 4 ----
+ gcc/doc/tm.texi.in | 2 --
+ gcc/final.c | 7 +------
+ gcc/regrename.c | 5 ++---
+ gcc/target.def | 19 -------------------
+ gcc/targhooks.c | 7 -------
+ gcc/targhooks.h | 1 -
+ gcc/toplev.c | 2 +-
+ 13 files changed, 10 insertions(+), 60 deletions(-)
+
+diff --git a/.cproject b/.cproject
+index 62b1c0f38dcb..b3cddaefb27b 100755
+--- .cproject
++++ .cproject
+@@ -42,6 +42,7 @@
+ <option id="gnu.cpp.compiler.option.preprocessor.def.807277038" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols">
+ <listOptionValue builtIn="false" value="IN_GCC=1"/>
+ <listOptionValue builtIn="false" value="HAVE_cc0=1"/>
++ <listOptionValue builtIn="false" value="__ECLIPSE__=1"/>
+ </option>
+ <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.cygwin.780175803" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input.cygwin"/>
+ </tool>
+@@ -56,12 +57,13 @@
+ <option id="gnu.c.compiler.option.preprocessor.def.symbols.1982594045" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols">
+ <listOptionValue builtIn="false" value="IN_GCC=1"/>
+ <listOptionValue builtIn="false" value="HAVE_cc0=1"/>
++ <listOptionValue builtIn="false" value="__ECLIPSE__=1"/>
+ </option>
+ <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.cygwin.2078467313" superClass="cdt.managedbuild.tool.gnu.c.compiler.input.cygwin"/>
+ </tool>
+ <tool id="cdt.managedbuild.tool.gnu.c.linker.cygwin.base.344641511" name="Cygwin C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.cygwin.base"/>
+ <tool id="cdt.managedbuild.tool.gnu.cpp.linker.cygwin.base.968200320" name="Cygwin C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.cygwin.base">
+- <option id="gnu.cpp.link.option.libs.260033787" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" valueType="libs"/>
++ <option id="gnu.cpp.link.option.libs.260033787" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs"/>
+ <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1537937183" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+ <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+ <additionalInput kind="additionalinput" paths="$(LIBS)"/>
+@@ -103,6 +105,7 @@
+ <option id="gnu.c.compiler.option.preprocessor.def.symbols.652362073" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols">
+ <listOptionValue builtIn="false" value="IN_GCC=1"/>
+ <listOptionValue builtIn="false" value="HAVE_cc0=1"/>
++ <listOptionValue builtIn="false" value="__ECLIPSE__=1"/>
+ </option>
+ <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1150724656" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+ </tool>
+@@ -115,6 +118,7 @@
+ <option id="gnu.cpp.compiler.option.preprocessor.def.625117841" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols">
+ <listOptionValue builtIn="false" value="IN_GCC=1"/>
+ <listOptionValue builtIn="false" value="HAVE_cc0=1"/>
++ <listOptionValue builtIn="false" value="__ECLIPSE__=1"/>
+ </option>
+ <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1133865092" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+ </tool>
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index efbcba2793ea..59aff9a1ff47 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170426
++20170430
+diff --git a/gcc/cfgbuild.c b/gcc/cfgbuild.c
+index 1f488dc54544..c1ec46ad8d7f 100644
+--- gcc/cfgbuild.c
++++ gcc/cfgbuild.c
+@@ -55,7 +55,6 @@ inside_basic_block_p (const rtx_insn *insn)
+ case DEBUG_INSN:
+ return true;
+
+- case DEBUG_IMPLICIT_PTR:
+ case JUMP_TABLE_DATA:
+ case BARRIER:
+ case NOTE:
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index 27831df2d543..419d59dc3871 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -839,13 +839,3 @@ read_only_operand (rtx operand)
+ return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P(operand);
+ return 1;
+ }
+-
+-reg_class_t
+-amiga_preferred_rename_class2 (reg_class_t rclass ATTRIBUTE_UNUSED, int regno)
+-{
+- if (regno == 0)
+- return D0_REGS;
+- if (regno == 8)
+- return A0_REGS;
+- return regno_reg_class[regno];
+-}
+diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h
+index 49dd90d745c3..e2a2b4cc11f6 100644
+--- gcc/config/m68k/amigaos.h
++++ gcc/config/m68k/amigaos.h
+@@ -486,7 +486,3 @@ amigaos_rtx_costs (rtx, machine_mode, int, int, int *, bool);
+ && GET_CODE(XEXP(XEXP(XEXP(x, 0), 1), 0)) == UNSPEC \
+ )
+
+-#undef TARGET_PREFERRED_RENAME_CLASS2
+-#define TARGET_PREFERRED_RENAME_CLASS2 amiga_preferred_rename_class2
+-reg_class_t
+-amiga_preferred_rename_class2(reg_class_t, int);
+diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
+index 6604514427fa..745910f9a331 100644
+--- gcc/doc/tm.texi
++++ gcc/doc/tm.texi
+@@ -2489,10 +2489,6 @@ only if neither labeling works.
+ A target hook that places additional preference on the register class to use when it is necessary to rename a register in class @var{rclass} to another class, or perhaps @var{NO_REGS}, if no preferred register class is found or hook @code{preferred_rename_class} is not implemented. Sometimes returning a more restrictive class makes better code. For example, on ARM, thumb-2 instructions using @code{LO_REGS} may be smaller than instructions using @code{GENERIC_REGS}. By returning @code{LO_REGS} from @code{preferred_rename_class}, code size can be reduced.
+ @end deftypefn
+
+-@deftypefn {Target Hook} reg_class_t TARGET_PREFERRED_RENAME_CLASS2 (reg_class_t @var{rclass}, int @var{regno})
+-A target hook that places additional preference on the register class to use when it is necessary to rename a register in class @var{rclass} to another class, or perhaps @var{NO_REGS}, if no preferred register class is found or hook @code{preferred_rename_class2} is not implemented. Sometimes returning a more restrictive class makes better code. For example, on ARM, thumb-2 instructions using @code{LO_REGS} may be smaller than instructions using @code{GENERIC_REGS}. By returning @code{LO_REGS} from @code{preferred_rename_class2}, code size can be reduced.
+-@end deftypefn
+-
+ @deftypefn {Target Hook} reg_class_t TARGET_PREFERRED_RELOAD_CLASS (rtx @var{x}, reg_class_t @var{rclass})
+ A target hook that places additional restrictions on the register class
+ to use when it is necessary to copy value @var{x} into a register in class
+diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
+index e4da2a94249b..f31c763991c5 100644
+--- gcc/doc/tm.texi.in
++++ gcc/doc/tm.texi.in
+@@ -2281,8 +2281,6 @@ only if neither labeling works.
+
+ @hook TARGET_PREFERRED_RENAME_CLASS
+
+-@hook TARGET_PREFERRED_RENAME_CLASS2
+-
+ @hook TARGET_PREFERRED_RELOAD_CLASS
+
+ @defmac PREFERRED_RELOAD_CLASS (@var{x}, @var{class})
+diff --git a/gcc/final.c b/gcc/final.c
+index 31f9b4815d75..55cf509611f7 100644
+--- gcc/final.c
++++ gcc/final.c
+@@ -2165,7 +2165,7 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
+
+ /* Ignore deleted insns. These can occur when we split insns (due to a
+ template of "#") while not optimizing. */
+- if (insn->deleted () || GET_CODE(insn) == VALUE || GET_CODE(insn) == CONST_FIXED || GET_CODE(insn) == DEBUG_IMPLICIT_PTR)
++ if (insn->deleted ())
+ return NEXT_INSN (insn);
+
+ switch (GET_CODE (insn))
+@@ -4430,17 +4430,12 @@ leaf_renumber_regs_insn (rtx in_rtx)
+ }
+ #endif
+
+-
+-extern void dump_insns(char const *);
+-
+ /* Turn the RTL into assembly. */
+ static unsigned int
+ rest_of_handle_final (void)
+ {
+ const char *fnname = get_fnname_from_decl (current_function_decl);
+
+-// dump_insns("final");
+-
+ assemble_start_function (current_function_decl, fnname);
+ final_start_function (get_insns (), asm_out_file, optimize);
+ final (get_insns (), asm_out_file, optimize);
+diff --git a/gcc/regrename.c b/gcc/regrename.c
+index 1ed6557ee713..b3818a80846d 100755
+--- gcc/regrename.c
++++ gcc/regrename.c
+@@ -406,9 +406,8 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class,
+
+ /* In the first pass, we force the renaming of registers that
+ don't belong to PREFERRED_CLASS to registers that do, even
+- though the latters were used not very long ago.
+- Also use a register if no best_new_reg was found till now */
+- if (((pass == 0 || !has_preferred_class)
++ though the latters were used not very long ago. */
++ if ((pass == 0
+ && !TEST_HARD_REG_BIT (reg_class_contents[preferred_class],
+ best_new_reg))
+ || tick[best_new_reg] > tick[new_reg])
+diff --git a/gcc/target.def b/gcc/target.def
+index d0208812d83b..20f2b32da1e9 100644
+--- gcc/target.def
++++ gcc/target.def
+@@ -5170,25 +5170,6 @@ DEFHOOK
+ reg_class_t, (reg_class_t rclass),
+ default_preferred_rename_class)
+
+-/*A target hook that places additional preference on the register
+- class
+- */
+-DEFHOOK
+-(preferred_rename_class2,
+- "A target hook that places additional preference on the register\
+- class to use when it is necessary to rename a register in class\
+- @var{rclass} to another class, or perhaps @var{NO_REGS}, if no\
+- preferred register class is found or hook @code{preferred_rename_class2}\
+- is not implemented.\
+- Sometimes returning a more restrictive class makes better code. For\
+- example, on ARM, thumb-2 instructions using @code{LO_REGS} may be\
+- smaller than instructions using @code{GENERIC_REGS}. By returning\
+- @code{LO_REGS} from @code{preferred_rename_class2}, code size can\
+- be reduced.",
+- reg_class_t, (reg_class_t rclass, int regno),
+- default_preferred_rename_class2)
+-
+-
+ /* This target hook allows the backend to avoid unsafe substitution
+ during register allocation. */
+ DEFHOOK
+diff --git a/gcc/targhooks.c b/gcc/targhooks.c
+index e106af7b261d..a34227705d2b 100644
+--- gcc/targhooks.c
++++ gcc/targhooks.c
+@@ -1542,13 +1542,6 @@ default_preferred_rename_class (reg_class_t rclass ATTRIBUTE_UNUSED)
+ return NO_REGS;
+ }
+
+-/* The default implementation of TARGET_PREFERRED_RENAME_CLASS2. */
+-reg_class_t
+-default_preferred_rename_class2 (reg_class_t rclass, int regno ATTRIBUTE_UNUSED)
+-{
+- return targetm.preferred_rename_class(rclass);
+-}
+-
+ /* The default implementation of TARGET_CLASS_LIKELY_SPILLED_P. */
+
+ bool
+diff --git a/gcc/targhooks.h b/gcc/targhooks.h
+index 0a21ef982a65..7687c39b53b5 100644
+--- gcc/targhooks.h
++++ gcc/targhooks.h
+@@ -204,7 +204,6 @@ extern bool default_profile_before_prologue (void);
+ extern reg_class_t default_preferred_reload_class (rtx, reg_class_t);
+ extern reg_class_t default_preferred_output_reload_class (rtx, reg_class_t);
+ extern reg_class_t default_preferred_rename_class (reg_class_t rclass);
+-extern reg_class_t default_preferred_rename_class2 (reg_class_t rclass, int regno);
+ extern bool default_class_likely_spilled_p (reg_class_t);
+ extern unsigned char default_class_max_nregs (reg_class_t, machine_mode);
+
+diff --git a/gcc/toplev.c b/gcc/toplev.c
+index 83800763f30d..59604e56195b 100644
+--- gcc/toplev.c
++++ gcc/toplev.c
+@@ -1324,7 +1324,7 @@ process_options (void)
+ flag_web = flag_unroll_loops || flag_peel_loops;
+
+ if (flag_rename_registers == AUTODETECT_VALUE)
+- flag_rename_registers = flag_unroll_loops || flag_peel_loops || optimize >= 2;
++ flag_rename_registers = flag_unroll_loops || flag_peel_loops;
+
+ if (flag_non_call_exceptions)
+ flag_asynchronous_unwind_tables = 1;
+
+From beb1cfb6a364fbe542b38cc4a4206219b465a671 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 2 May 2017 22:42:17 +0200
+Subject: [PATCH 106/303] @B fix stack frame shrink/removal with frame pointer,
+ @I some internal changes
+
+---
+ gcc/bbb-opts.c | 236 +++++++++++++++++++++++++++++++++++---------------------
+ gcc/regrename.c | 5 +-
+ 2 files changed, 153 insertions(+), 88 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 99c49db4238d..6a27fcf72544 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -75,7 +75,12 @@ bool be_very_verbose;
+ bool be_verbose;
+
+ #ifdef __ECLIPSE__
+-extern char * string_bbb_opts;
++//extern char * string_bbb_opts;
++#define FIRST_PSEUDO_REGISTER 25
++#define FRAME_POINTER_REGNUM 13
++#define STACK_POINTER_REGNUM 15
++#define NOTICE_UPDATE_CC(a,b)
++#define Pmode SImode
+ #endif
+ extern struct lang_hooks lang_hooks;
+
+@@ -138,28 +143,25 @@ class insn_info
+ bool jump;
+ bool call;
+ bool compare;
+- bool dst_reg;
+- bool src_reg;
+ bool dst_mem;
+ bool src_mem;
+ bool dst_plus;
+ bool src_plus;
+ bool src_const;
+
+- int dst_regno;
+- int dst_mem_reg;
++ rtx dst_reg;
++ rtx dst_mem_reg;
++ rtx src_reg;
++ rtx src_mem_reg;
+ unsigned dst_mem_addr;
+
+- int src_regno;
+- int src_mem_regno;
+ unsigned src_intval;
+
+ public:
+ insn_info (rtx_insn * i = 0, int p = 0) :
+ insn (i), myuse (0), hard (0), use (0), def (0), proepi (p), stack (false), label (false), jump (false), call (
+- false), compare (false), dst_reg (false), src_reg (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus (
+- false), src_const (false), dst_regno (-1), dst_mem_reg (-1), dst_mem_addr (0), src_regno (-1), src_mem_regno (
+- -1), src_intval (0)
++ false), compare (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus (false), src_const (
++ false), dst_reg (0), dst_mem_reg (0), src_reg (0), src_mem_reg (0), dst_mem_addr (0), src_intval (0)
+ {
+ }
+
+@@ -173,7 +175,7 @@ class insn_info
+ swap_adds (rtx_insn * newinsn, insn_info & ii);
+
+ void
+- immediate2base (unsigned regno, unsigned base);
++ absolute2base (unsigned regno, unsigned base);
+
+ inline bool
+ is_dst_reg () const
+@@ -196,13 +198,13 @@ class insn_info
+ inline bool
+ has_dst_memreg () const
+ {
+- return dst_mem_reg >= 0;
++ return dst_mem_reg;
+ }
+
+ inline bool
+ has_dst_addr () const
+ {
+- return dst_mem_addr != 0;
++ return dst_mem_addr;
+ }
+
+ inline bool
+@@ -232,25 +234,55 @@ class insn_info
+ inline bool
+ is_src_reg () const
+ {
+- return src_reg;
++ return src_reg && !src_plus;
++ }
++
++ inline bool
++ is_src_plus () const
++ {
++ return src_reg && src_plus;
++ }
++
++ inline bool
++ is_src_mem_plus () const
++ {
++ return src_mem && src_plus;
+ }
+
+ inline int
+ get_dst_regno () const
+ {
+- return dst_regno;
++ return dst_reg ? REGNO(dst_reg) : -1;
+ }
+
+ inline int
+ get_src_regno () const
+ {
+- return src_regno;
++ return src_reg ? REGNO(src_reg) : -1;
+ }
+
+- inline bool
+- is_src_plus () const
++ inline rtx
++ get_src_reg () const
++ {
++ return src_reg;
++ }
++
++ inline rtx
++ get_dst_reg () const
++ {
++ return dst_reg;
++ }
++
++ inline int
++ get_src_mem_regno () const
++ {
++ return src_mem_reg ? REGNO(src_mem_reg) : -1;
++ }
++
++ inline int
++ get_src_intval () const
+ {
+- return src_plus;
++ return src_intval;
+ }
+
+ inline bool
+@@ -360,7 +392,7 @@ class insn_info
+ }
+
+ inline void
+- set_use(unsigned u)
++ set_use (unsigned u)
+ {
+ use = u;
+ }
+@@ -431,6 +463,13 @@ class insn_info
+ return *this;
+ }
+
++ inline insn_info &
++ or_use (insn_info const & o)
++ {
++ use |= o.myuse | o.def | o.hard;
++ return *this;
++ }
++
+ inline insn_info &
+ drop_def ()
+ {
+@@ -524,6 +563,10 @@ class insn_info
+ {
+ return def & ~hard & ~use & 0x7fff;
+ }
++
++ void
++ set_insn (rtx_insn * newinsn);
++
+ };
+
+ void
+@@ -634,15 +677,14 @@ insn_info::fledder (rtx set)
+
+ if (REG_P(dst))
+ {
+- dst_reg = true;
+- dst_regno = REGNO(dst);
++ dst_reg = dst;
+ }
+ else if (MEM_P(dst))
+ {
+ dst_mem = true;
+ rtx mem = XEXP(dst, 0);
+ if (REG_P(mem))
+- dst_mem_reg = REGNO(mem);
++ dst_mem_reg = mem;
+ else if (GET_CODE(mem) == CONST_INT)
+ dst_mem_addr = INTVAL(mem);
+ else if (GET_CODE(mem) == PLUS)
+@@ -652,7 +694,7 @@ insn_info::fledder (rtx set)
+ rtx konst = XEXP(mem, 1);
+ if (REG_P(reg) && GET_CODE(konst) == CONST_INT)
+ {
+- dst_mem_reg = REGNO(reg);
++ dst_mem_reg = reg;
+ dst_mem_addr = INTVAL(konst);
+ }
+ }
+@@ -660,15 +702,14 @@ insn_info::fledder (rtx set)
+
+ if (REG_P(src))
+ {
+- src_reg = true;
+- src_regno = REGNO(src);
++ src_reg = src;
+ }
+ else if (MEM_P(src))
+ {
+ src_mem = true;
+ rtx mem = XEXP(src, 0);
+ if (REG_P(mem))
+- src_mem_regno = REGNO(mem);
++ src_mem_reg = mem;
+ else if (GET_CODE(mem) == CONST_INT)
+ src_intval = INTVAL(mem);
+ else if (GET_CODE(mem) == PLUS)
+@@ -678,7 +719,7 @@ insn_info::fledder (rtx set)
+ rtx konst = XEXP(mem, 1);
+ if (REG_P(reg) && GET_CODE(konst) == CONST_INT)
+ {
+- src_mem_regno = REGNO(reg);
++ src_mem_reg = reg;
+ src_const = true;
+ src_intval = INTVAL(konst);
+ }
+@@ -698,14 +739,13 @@ insn_info::fledder (rtx set)
+ {
+ if (GET_CODE(konst) == CONST_INT)
+ {
+- src_regno = REGNO(reg);
++ src_reg = reg;
+ src_const = true;
+ src_intval = INTVAL(konst);
+ }
+ else if (REG_P(konst))
+ {
+- src_reg = true;
+- src_regno = REGNO(konst);
++ src_reg = konst;
+ }
+ }
+ }
+@@ -815,7 +855,7 @@ insn_info::plus_to_move (rtx_insn * newinsn)
+ {
+ insn = newinsn;
+ src_plus = false;
+- src_reg = true;
++ src_reg = XEXP(PATTERN (newinsn), 1);
+ insn2index.insert (std::make_pair (insn, this));
+ // usage flags did not change
+ }
+@@ -834,7 +874,14 @@ insn_info::swap_adds (rtx_insn * newinsn, insn_info & ii)
+ }
+
+ void
+-insn_info::immediate2base (unsigned regno, unsigned base)
++insn_info::set_insn (rtx_insn * newinsn)
++{
++ insn = newinsn;
++ fledder (PATTERN (insn));
++}
++
++void
++insn_info::absolute2base (unsigned regno, unsigned base)
+ {
+ rtx set = PATTERN (get_insn ());
+ rtx src = SET_SRC(set);
+@@ -844,19 +891,18 @@ insn_info::immediate2base (unsigned regno, unsigned base)
+ unsigned offset = addr - base;
+
+ rtx pattern;
++ rtx reg = gen_raw_REG (SImode, regno);
+ if (base == addr)
+- pattern = gen_rtx_SET(gen_rtx_MEM (mode, gen_raw_REG (SImode, regno)), SET_SRC(set));
++ pattern = gen_rtx_SET(gen_rtx_MEM (mode, reg), src);
+ else
+- pattern = gen_rtx_SET(
+- gen_rtx_MEM (mode, gen_rtx_PLUS(SImode, gen_raw_REG (SImode, regno), gen_rtx_CONST_INT(SImode, offset))),
+- SET_SRC(set));
++ pattern = gen_rtx_SET(gen_rtx_MEM (mode, gen_rtx_PLUS(SImode, reg, gen_rtx_CONST_INT(SImode, offset))), src);
+
+ SET_INSN_DELETED(insn);
+ insn = emit_insn_after (pattern, insn);
+
+ mark_use (regno);
+
+- dst_mem_reg = regno;
++ dst_mem_reg = reg;
+ dst_mem = true;
+ dst_mem_addr = offset;
+ dst_plus = offset != 0;
+@@ -908,7 +954,7 @@ append_reg_usage (FILE * f, rtx_insn * insn)
+ insn_info & ii = *i->second;
+
+ if (f != stderr)
+- fprintf (f, "\n\t\t\t\t\t\t| ");
++ fprintf (f, "\n\t\t\t\t\t\t|%c ", ii.is_stack () ? 's' : ' ');
+
+ for (int j = 0; j < 8; ++j)
+ if (ii.is_use (j) || ii.is_def (j))
+@@ -1046,7 +1092,7 @@ update_insn_infos (void)
+ if (!use.is_def (FIRST_PSEUDO_REGISTER))
+ {
+ CC_STATUS_INIT;
+- NOTICE_UPDATE_CC(PATTERN (insn), insn);
++ NOTICE_UPDATE_CC (PATTERN (insn), insn);
+ if (cc_status.value1 || cc_status.value2)
+ use.mark_def (FIRST_PSEUDO_REGISTER);
+ }
+@@ -1706,7 +1752,7 @@ opt_strcpy ()
+ if (REG_P(dst) && CONST_INT_P(src) && INTVAL(src) == 0 && is_reg_dead (REGNO(dst), index))
+ {
+ /* now check via NOTICE_UPDATE_CC*/
+- NOTICE_UPDATE_CC(PATTERN (reg2x), reg2x);
++ NOTICE_UPDATE_CC (PATTERN (reg2x), reg2x);
+ if (cc_status.flags == 0 && rtx_equal_p (dst, cc_status.value2))
+ {
+ int num_clobbers_to_add = 0;
+@@ -2074,13 +2120,13 @@ opt_merge_add (void)
+ insn_info & ii1 = infos[index + 1];
+ insn_info & ii2 = infos[index + 2];
+
+- if (!ii2.is_dst_reg () || ii2.is_dst_mem ())
++ if (!ii2.is_dst_reg ())
+ {
+ index += 2;
+ continue;
+ }
+
+- if (!ii1.is_dst_reg () || ii1.is_dst_mem ())
++ if (!ii1.is_dst_reg ())
+ {
+ ++index;
+ continue;
+@@ -2089,7 +2135,7 @@ opt_merge_add (void)
+ if (!ii0.is_dst_reg () || !ii0.is_src_plus () || !ii1.is_src_plus () || !ii2.is_src_plus ())
+ continue;
+
+- if (ii0.is_src_mem () || !ii0.is_src_const () || !ii1.is_src_reg () || ii2.is_src_mem () || !ii2.is_src_const ())
++ if (!ii0.is_src_const () || !ii2.is_src_const () || ii0.get_src_intval () != ii2.get_src_intval ())
+ continue;
+
+ if (ii0.get_dst_regno () != ii1.get_dst_regno () || ii1.get_src_regno () != ii2.get_dst_regno ())
+@@ -2098,7 +2144,7 @@ opt_merge_add (void)
+ rtx_insn * insn1 = ii1.get_insn ();
+
+ CC_STATUS_INIT;
+- NOTICE_UPDATE_CC(PATTERN (insn1), insn1);
++ NOTICE_UPDATE_CC (PATTERN (insn1), insn1);
+ if (cc_status.value1 || cc_status.value2)
+ continue;
+
+@@ -2182,6 +2228,7 @@ opt_shrink_stack_frame (void)
+ {
+ rtx set = XVECEXP(pattern, 0, 0);
+ rtx dst = SET_DEST(set);
++ ii.mark_stack ();
+ /* ignore link a5 */
+ if (REG_P(dst) && REGNO(dst) == FRAME_POINTER_REGNUM)
+ {
+@@ -2190,11 +2237,6 @@ opt_shrink_stack_frame (void)
+ set = XVECEXP(pattern, 0, 2);
+ a5offset = INTVAL(XEXP(SET_SRC(set), 1));
+ }
+- else
+- {
+- /* use movem */
+- ii.mark_stack ();
+- }
+ ++pos;
+ continue;
+ }
+@@ -2269,6 +2311,7 @@ opt_shrink_stack_frame (void)
+ {
+ rtx set = XVECEXP(pattern, 0, 0);
+ rtx dst = SET_DEST(set);
++ ii.mark_stack ();
+ /* unlink is last. */
+ if (REG_P(dst) && REGNO(dst) == FRAME_POINTER_REGNUM)
+ {
+@@ -2276,8 +2319,6 @@ opt_shrink_stack_frame (void)
+ break;
+ }
+
+- /* movem. */
+- ii.mark_stack ();
+ }
+ else if (GET_CODE(pattern) == SET)
+ {
+@@ -2295,6 +2336,12 @@ opt_shrink_stack_frame (void)
+ if (REG_P(reg) && REGNO(reg) == STACK_POINTER_REGNUM)
+ ii.mark_stack ();
+ }
++ else if (GET_CODE(postinc) == PLUS)
++ {
++ rtx a5 = XEXP(postinc, 0);
++ if (REG_P(a5) && REGNO(a5) == FRAME_POINTER_REGNUM)
++ ii.mark_stack ();
++ }
+ }
+ }
+ }
+@@ -2306,16 +2353,17 @@ opt_shrink_stack_frame (void)
+ for (unsigned i = 0; i < infos.size (); ++i)
+ {
+ insn_info & jj = infos[i];
+- if (jj.is_stack ())
++ if (jj.in_proepi ())
+ continue;
+
+- ii.merge (jj);
++ ii.or_use (jj);
+ }
+- unsigned freemask = ~ii.get_use ();
++ unsigned freemask = ~ii.get_use () & 0x7fff;
+
+ rtx a7 = gen_raw_REG (SImode, STACK_POINTER_REGNUM);
+ rtx a5 = gen_raw_REG (SImode, FRAME_POINTER_REGNUM);
+
++ unsigned changed = 0;
+ unsigned adjust = 0;
+ /* now all push/pop insns are in temp. */
+ for (unsigned i = 0; i < infos.size (); ++i)
+@@ -2339,8 +2387,8 @@ opt_shrink_stack_frame (void)
+ clobbers.push_back (set);
+ continue;
+ }
+- rtx src = SET_SRC(set);
+ rtx dst = SET_DEST(set);
++ rtx src = SET_SRC(set);
+ rtx reg;
+ if (MEM_P(src))
+ reg = dst;
+@@ -2349,6 +2397,13 @@ opt_shrink_stack_frame (void)
+ else
+ continue;
+
++ if (REGNO(reg) == FRAME_POINTER_REGNUM)
++ {
++ // mark as "do not touch"
++ clobbers.push_back (reg);
++ break;
++ }
++
+ if (i < prologueend)
+ paramstart += 4;
+ unsigned regbit = 1 << REGNO(reg);
+@@ -2378,6 +2433,7 @@ opt_shrink_stack_frame (void)
+ log ("shrinking stack frame from %d to %d\n", XVECLEN(pattern, 0) - add1, regs.size ());
+ if (regs.size () <= 2)
+ {
++ changed = 1;
+ for (unsigned k = 0; k < regs.size (); ++k)
+ {
+ rtx reg = regs[k];
+@@ -2453,6 +2509,7 @@ opt_shrink_stack_frame (void)
+ emit_insn_after (parallel, insn);
+ }
+ SET_INSN_DELETED(insn);
++ changed = 1;
+ }
+ }
+ else
+@@ -2470,6 +2527,7 @@ opt_shrink_stack_frame (void)
+ adjust += REGNO(src) > STACK_POINTER_REGNUM ? 12 : 4;
+ log ("remove push for %s\n", reg_names[REGNO(src)]);
+ SET_INSN_DELETED(insn);
++ ++changed;
+ }
+ }
+ else
+@@ -2481,6 +2539,7 @@ opt_shrink_stack_frame (void)
+ {
+ log ("remove pop for %s\n", reg_names[REGNO(dst)]);
+ SET_INSN_DELETED(insn);
++ ++changed;
+ }
+ }
+ }
+@@ -2524,42 +2583,47 @@ opt_shrink_stack_frame (void)
+
+ if (usea5 && a5offset == -4)
+ {
+- for (std::vector<int>::iterator i = a5pos.begin (); i != a5pos.end (); ++i)
+- {
+- insn_info & ii = infos[*i];
+- ii.mark_stack ();
+- }
+- for (unsigned i = 0; i < infos.size (); ++i)
+- {
+- insn_info ii;
+- insn_info & jj = infos[i];
+- if (jj.is_stack ())
+- continue;
+-
+- ii.merge (jj);
+- }
+- unsigned freemask = ~ii.get_use ();
+-
+ if (freemask & (1 << FRAME_POINTER_REGNUM))
+ {
+ log ("dropping unused frame pointer\n");
+ for (std::vector<int>::iterator i = a5pos.begin (); i != a5pos.end (); ++i)
+ SET_INSN_DELETED(infos[*i].get_insn ());
++
++ /* convert parameter access via a5 into a7. */
++ for (unsigned i = 0; i < infos.size (); ++i)
++ {
++ insn_info & ii = infos[i];
++
++ if (ii.is_dst_reg () && ii.get_src_mem_regno () == FRAME_POINTER_REGNUM)
++ {
++ rtx x = gen_rtx_CONST_INT (SImode, ii.get_src_intval () - 4);
++ rtx p = gen_rtx_PLUS(SImode, a7, x);
++ rtx pattern = gen_rtx_SET(copy_reg (ii.get_dst_reg (), -1), gen_rtx_MEM (SImode, p));
++ set_insn_deleted (ii.get_insn ());
++ rtx_insn * newinsn = emit_insn_after (pattern, ii.get_insn ());
++ ii.plus_to_move (newinsn);
++ }
++ }
++
++ ++changed;
+ }
+ }
+
+- return 0;
++ return changed;
+ }
+
++/*
++ * Convert a series of move into absolute address into register based moves.
++ */
+ static unsigned
+-opt_immediate (void)
++opt_absolute (void)
+ {
+ unsigned change_count = 0;
+
+ for (unsigned i = 0; i < infos.size (); ++i)
+ {
+ insn_info & ii = infos[i];
+- if (!ii.is_dst_mem () || !ii.has_dst_addr () || ii.has_dst_memreg())
++ if (!ii.is_dst_mem () || !ii.has_dst_addr () || ii.has_dst_memreg ())
+ continue;
+
+ unsigned freemask = ~(ii.get_use () | ii.get_def ()) & 0x7f00;
+@@ -2580,7 +2644,7 @@ opt_immediate (void)
+ if (!freemask)
+ break;
+
+- if (jj.is_dst_mem () && jj.has_dst_addr () && !jj.has_dst_memreg())
++ if (jj.is_dst_mem () && jj.has_dst_addr () && !jj.has_dst_memreg ())
+ {
+ unsigned addr = jj.get_dst_addr ();
+ if (addr < base)
+@@ -2600,20 +2664,20 @@ opt_immediate (void)
+ for (auto k = found.begin (); k != found.end (); ++k)
+ {
+ insn_info & kk = infos[*k];
+- kk.immediate2base (regno, base);
++ kk.absolute2base (regno, base);
+ }
+
+ // load base into reg
+ rtx lea = gen_rtx_SET(gen_raw_REG (SImode, regno), gen_rtx_CONST_INT (SImode, base));
+ rtx_insn * insn = emit_insn_before (lea, ii.get_insn ());
+ insn_info nn (insn);
+- nn.set_use(ii.get_use());
+- nn.scan();
++ nn.set_use (ii.get_use ());
++ nn.scan ();
+ nn.fledder (lea);
+ nn.mark_def (regno);
+ infos.insert (infos.begin () + i, nn);
+ while (i++ < j)
+- infos[i].mark_use(regno);
++ infos[i].mark_use (regno);
+ ++j;
+ ++change_count;
+ }
+@@ -2686,7 +2750,7 @@ namespace
+ pass_bbb_optimizations::execute_bbb_optimizations (void)
+ {
+ be_very_verbose = strchr (string_bbb_opts, 'V');
+- be_verbose = be_very_verbose || strchr (string_bbb_opts, 'v');
++ be_verbose = be_very_verbose || strchr (string_bbb_opts, 'v') || 1;
+
+ bool do_opt_strcpy = strchr (string_bbb_opts, 's') || strchr (string_bbb_opts, '+');
+ bool do_commute_add_move = strchr (string_bbb_opts, 'a') || strchr (string_bbb_opts, '+');
+@@ -2696,7 +2760,7 @@ namespace
+ bool do_elim_dead_assign = strchr (string_bbb_opts, 'e') || strchr (string_bbb_opts, '+');
+ bool do_bb_reg_rename = strchr (string_bbb_opts, 'r') || strchr (string_bbb_opts, '+');
+ bool do_shrink_stack_frame = strchr (string_bbb_opts, 'f') || strchr (string_bbb_opts, '+');
+- bool do_immediate = strchr (string_bbb_opts, 'i') || strchr (string_bbb_opts, '+');
++ bool do_absolute = strchr (string_bbb_opts, 'b') || strchr (string_bbb_opts, '+');
+
+ for (;;)
+ {
+@@ -2720,8 +2784,8 @@ namespace
+ if (do_elim_dead_assign && opt_elim_dead_assign ())
+ done = 0, update_insns ();
+
+- if (do_immediate && opt_immediate ())
+- done = 0, update_insns ();
++ if (do_absolute && opt_absolute ())
++ done = 0;
+
+ if (do_bb_reg_rename)
+ {
+@@ -2738,8 +2802,8 @@ namespace
+
+ if (do_shrink_stack_frame)
+ {
+- opt_shrink_stack_frame ();
+- update_insns ();
++ if (opt_shrink_stack_frame ())
++ update_insns ();
+ }
+
+ if (strchr (string_bbb_opts, 'X') || strchr (string_bbb_opts, 'x'))
+diff --git a/gcc/regrename.c b/gcc/regrename.c
+index b3818a80846d..1ed6557ee713 100755
+--- gcc/regrename.c
++++ gcc/regrename.c
+@@ -406,8 +406,9 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class,
+
+ /* In the first pass, we force the renaming of registers that
+ don't belong to PREFERRED_CLASS to registers that do, even
+- though the latters were used not very long ago. */
+- if ((pass == 0
++ though the latters were used not very long ago.
++ Also use a register if no best_new_reg was found till now */
++ if (((pass == 0 || !has_preferred_class)
+ && !TEST_HARD_REG_BIT (reg_class_contents[preferred_class],
+ best_new_reg))
+ || tick[best_new_reg] > tick[new_reg])
+
+From f3a773accb47542fef665cf044dad13366139ab5 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 3 May 2017 09:33:02 +0200
+Subject: [PATCH 107/303] @B fix shrink stack frame for 8 byte parameters
+
+---
+ gcc/bbb-opts.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 6a27fcf72544..e8000a01ce49 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -2598,7 +2598,8 @@ opt_shrink_stack_frame (void)
+ {
+ rtx x = gen_rtx_CONST_INT (SImode, ii.get_src_intval () - 4);
+ rtx p = gen_rtx_PLUS(SImode, a7, x);
+- rtx pattern = gen_rtx_SET(copy_reg (ii.get_dst_reg (), -1), gen_rtx_MEM (SImode, p));
++ rtx pattern = gen_rtx_SET(copy_reg (ii.get_dst_reg (), -1),
++ gen_rtx_MEM (GET_MODE(ii.get_dst_reg ()), p));
+ set_insn_deleted (ii.get_insn ());
+ rtx_insn * newinsn = emit_insn_after (pattern, ii.get_insn ());
+ ii.plus_to_move (newinsn);
+
+From c391e554b0a0d6fad5b78ed5ace23eab60cbbe3d Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 3 May 2017 12:57:04 +0200
+Subject: [PATCH 108/303] @N opt_absolute also optimizes symbol refs
+
+---
+ gcc/bbb-opts.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 98 insertions(+), 8 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index e8000a01ce49..d54da597123b 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -81,6 +81,7 @@ bool be_verbose;
+ #define STACK_POINTER_REGNUM 15
+ #define NOTICE_UPDATE_CC(a,b)
+ #define Pmode SImode
++#define PIC_REG 12
+ #endif
+ extern struct lang_hooks lang_hooks;
+
+@@ -151,8 +152,10 @@ class insn_info
+
+ rtx dst_reg;
+ rtx dst_mem_reg;
++ rtx dst_symbol;
+ rtx src_reg;
+ rtx src_mem_reg;
++ rtx src_symbol;
+ unsigned dst_mem_addr;
+
+ unsigned src_intval;
+@@ -161,7 +164,8 @@ class insn_info
+ insn_info (rtx_insn * i = 0, int p = 0) :
+ insn (i), myuse (0), hard (0), use (0), def (0), proepi (p), stack (false), label (false), jump (false), call (
+ false), compare (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus (false), src_const (
+- false), dst_reg (0), dst_mem_reg (0), src_reg (0), src_mem_reg (0), dst_mem_addr (0), src_intval (0)
++ false), dst_reg (0), dst_mem_reg (0), dst_symbol (0), src_reg (0), src_mem_reg (0), src_symbol (0), dst_mem_addr (
++ 0), src_intval (0)
+ {
+ }
+
+@@ -201,6 +205,12 @@ class insn_info
+ return dst_mem_reg;
+ }
+
++ inline rtx
++ get_dst_symbol () const
++ {
++ return dst_symbol;
++ }
++
+ inline bool
+ has_dst_addr () const
+ {
+@@ -687,6 +697,8 @@ insn_info::fledder (rtx set)
+ dst_mem_reg = mem;
+ else if (GET_CODE(mem) == CONST_INT)
+ dst_mem_addr = INTVAL(mem);
++ else if (GET_CODE(mem) == SYMBOL_REF)
++ dst_symbol = mem;
+ else if (GET_CODE(mem) == PLUS)
+ {
+ dst_plus = true;
+@@ -698,6 +710,20 @@ insn_info::fledder (rtx set)
+ dst_mem_addr = INTVAL(konst);
+ }
+ }
++ else if (GET_CODE(mem) == CONST)
++ {
++ mem = XEXP(mem, 0);
++ if (GET_CODE(mem) == PLUS)
++ {
++ rtx sym = XEXP(mem, 0);
++ if (GET_CODE(sym) == SYMBOL_REF)
++ {
++ dst_plus = true;
++ dst_symbol = sym;
++ dst_mem_addr = INTVAL(XEXP(mem, 1));
++ }
++ }
++ }
+ }
+
+ if (REG_P(src))
+@@ -712,6 +738,8 @@ insn_info::fledder (rtx set)
+ src_mem_reg = mem;
+ else if (GET_CODE(mem) == CONST_INT)
+ src_intval = INTVAL(mem);
++ else if (GET_CODE(mem) == SYMBOL_REF)
++ src_symbol = mem;
+ else if (GET_CODE(mem) == PLUS)
+ {
+ src_plus = true;
+@@ -724,6 +752,20 @@ insn_info::fledder (rtx set)
+ src_intval = INTVAL(konst);
+ }
+ }
++ else if (GET_CODE(mem) == CONST)
++ {
++ mem = XEXP(mem, 0);
++ if (GET_CODE(mem) == PLUS)
++ {
++ rtx sym = XEXP(mem, 0);
++ if (GET_CODE(sym) == SYMBOL_REF)
++ {
++ src_plus = true;
++ src_symbol = sym;
++ src_intval = INTVAL(XEXP(mem, 1));
++ }
++ }
++ }
+ }
+ else if (GET_CODE(src) == CONST_INT)
+ {
+@@ -749,7 +791,6 @@ insn_info::fledder (rtx set)
+ }
+ }
+ }
+-
+ }
+
+ /* create a copy for a reg. Optional specify a new register number. */
+@@ -813,6 +854,7 @@ static std::vector<rtx_insn *> jumps;
+ static std::map<rtx_insn *, insn_info *> insn2index;
+
+ static insn_info * info0;
++static unsigned usable_regs;
+
+ static void
+ update_insn2index ()
+@@ -1107,6 +1149,27 @@ update_insn_infos (void)
+ }
+ ++pass;
+ }
++
++ /* fill the mask of general used regs. */
++ insn_info zz;
++ for (int i = 0; i < infos.size (); ++i)
++ {
++ insn_info & ii = infos[i];
++ if (ii.in_proepi () != 1)
++ break;
++
++ zz.or_use (ii);
++ }
++
++ /* always allow a0/a1, d0/d1. */
++ usable_regs = zz.get_use () | 0x303;
++ if (flag_pic)
++ usable_regs &= ~(1 << PIC_REG);
++
++ if (infos.size () && infos[0].is_use (FRAME_POINTER_REGNUM))
++ usable_regs &= ~(1 << FRAME_POINTER_REGNUM);
++
++ usable_regs &= ~(1 << STACK_POINTER_REGNUM);
+ }
+
+ /*
+@@ -2627,10 +2690,12 @@ opt_absolute (void)
+ if (!ii.is_dst_mem () || !ii.has_dst_addr () || ii.has_dst_memreg ())
+ continue;
+
+- unsigned freemask = ~(ii.get_use () | ii.get_def ()) & 0x7f00;
++ unsigned freemask = ~(ii.get_use () | ii.get_def ()) & 0x7f00 & usable_regs;
+ if (!freemask)
+ continue;
+
++ rtx with_symbol = ii.get_dst_symbol ();
++
+ std::vector<unsigned> found;
+ found.push_back (i);
+ unsigned base = ii.get_dst_addr ();
+@@ -2645,22 +2710,35 @@ opt_absolute (void)
+ if (!freemask)
+ break;
+
+- if (jj.is_dst_mem () && jj.has_dst_addr () && !jj.has_dst_memreg ())
++ if (jj.is_dst_mem () && jj.has_dst_addr () && !jj.has_dst_memreg () && jj.get_dst_symbol () == with_symbol)
+ {
+ unsigned addr = jj.get_dst_addr ();
+ if (addr < base)
+ base = addr;
+- if (addr - base > 0x7ffc)
+- continue;
+
+ found.push_back (j);
+ }
+ }
+
++ if (freemask && found.size () > 2)
++ {
++ /* check again. */
++ for (auto k = found.begin (); k != found.end ();)
++ {
++ insn_info & kk = infos[*k];
++ if (kk.get_dst_addr () - base > 0x7ffc)
++ found.erase (k);
++ else
++ ++k;
++ }
++ }
+ if (freemask && found.size () > 2)
+ {
+ unsigned regno = bit2regno (freemask);
+- log ("modifying %d immediate using %s\n", found.size (), reg_names[regno]);
++ if (with_symbol)
++ log ("modifying %d symbol addresses using %s\n", found.size (), reg_names[regno]);
++ else
++ log ("modifying %d absolute addresses using %s\n", found.size (), reg_names[regno]);
+
+ for (auto k = found.begin (); k != found.end (); ++k)
+ {
+@@ -2669,7 +2747,19 @@ opt_absolute (void)
+ }
+
+ // load base into reg
+- rtx lea = gen_rtx_SET(gen_raw_REG (SImode, regno), gen_rtx_CONST_INT (SImode, base));
++ rtx lea;
++
++ if (with_symbol)
++ {
++ if (base)
++ lea = gen_rtx_SET(
++ gen_raw_REG (SImode, regno),
++ gen_rtx_CONST(SImode, gen_rtx_PLUS(SImode, with_symbol, gen_rtx_CONST_INT (SImode, base))));
++ else
++ lea = gen_rtx_SET(gen_raw_REG (SImode, regno), with_symbol);
++ }
++ else
++ lea = gen_rtx_SET(gen_raw_REG (SImode, regno), gen_rtx_CONST_INT (SImode, base));
+ rtx_insn * insn = emit_insn_before (lea, ii.get_insn ());
+ insn_info nn (insn);
+ nn.set_use (ii.get_use ());
+
+From 09c30ec6c5e0bd07fa3d300c2d45cec75f67c783 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 4 May 2017 11:42:43 +0200
+Subject: [PATCH 109/303] @B fix dropping stack frame - now only dropped if
+ really unused
+
+---
+ gcc/bbb-opts.c | 246 +++++++++++++++++++++++++++++++++++++++++++++------------
+ 1 file changed, 197 insertions(+), 49 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index d54da597123b..a4bb1e0a97a3 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -150,6 +150,8 @@ class insn_info
+ bool src_plus;
+ bool src_const;
+
++ machine_mode mode;
++
+ rtx dst_reg;
+ rtx dst_mem_reg;
+ rtx dst_symbol;
+@@ -158,14 +160,14 @@ class insn_info
+ rtx src_symbol;
+ unsigned dst_mem_addr;
+
+- unsigned src_intval;
++ unsigned src_mem_addr;
+
+ public:
+ insn_info (rtx_insn * i = 0, int p = 0) :
+ insn (i), myuse (0), hard (0), use (0), def (0), proepi (p), stack (false), label (false), jump (false), call (
+ false), compare (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus (false), src_const (
+- false), dst_reg (0), dst_mem_reg (0), dst_symbol (0), src_reg (0), src_mem_reg (0), src_symbol (0), dst_mem_addr (
+- 0), src_intval (0)
++ false), mode (VOIDmode), dst_reg (0), dst_mem_reg (0), dst_symbol (0), src_reg (0), src_mem_reg (0), src_symbol (
++ 0), dst_mem_addr (0), src_mem_addr (0)
+ {
+ }
+
+@@ -179,7 +181,7 @@ class insn_info
+ swap_adds (rtx_insn * newinsn, insn_info & ii);
+
+ void
+- absolute2base (unsigned regno, unsigned base);
++ absolute2base (unsigned regno, unsigned base, rtx with_symbol);
+
+ inline bool
+ is_dst_reg () const
+@@ -205,18 +207,35 @@ class insn_info
+ return dst_mem_reg;
+ }
+
++ inline bool
++ has_src_memreg () const
++ {
++ return src_mem_reg;
++ }
++
+ inline rtx
+ get_dst_symbol () const
+ {
+ return dst_symbol;
+ }
+
++ inline rtx
++ get_src_symbol () const
++ {
++ return src_symbol;
++ }
+ inline bool
+ has_dst_addr () const
+ {
+ return dst_mem_addr;
+ }
+
++ inline bool
++ has_src_addr () const
++ {
++ return src_mem_addr;
++ }
++
+ inline bool
+ is_label () const
+ {
+@@ -241,6 +260,12 @@ class insn_info
+ return dst_mem_addr;
+ }
+
++ inline unsigned
++ get_src_addr () const
++ {
++ return src_mem_addr;
++ }
++
+ inline bool
+ is_src_reg () const
+ {
+@@ -292,7 +317,7 @@ class insn_info
+ inline int
+ get_src_intval () const
+ {
+- return src_intval;
++ return src_mem_addr;
+ }
+
+ inline bool
+@@ -401,6 +426,12 @@ class insn_info
+ return use;
+ }
+
++ inline unsigned
++ get_myuse () const
++ {
++ return myuse;
++ }
++
+ inline void
+ set_use (unsigned u)
+ {
+@@ -467,6 +498,7 @@ class insn_info
+ inline insn_info &
+ merge (insn_info const & o)
+ {
++ myuse = o.myuse;
+ use = (use & ~o.def) | o.use;
+ def |= o.def;
+ hard |= o.hard;
+@@ -577,6 +609,8 @@ class insn_info
+ void
+ set_insn (rtx_insn * newinsn);
+
++ void
++ a5_to_a7 (rtx a7);
+ };
+
+ void
+@@ -677,6 +711,8 @@ insn_info::fledder (rtx set)
+ rtx dst = SET_DEST(set);
+ rtx src = SET_SRC(set);
+
++ mode = GET_MODE(dst);
++
+ if (dst == cc0_rtx)
+ {
+ compare = true;
+@@ -737,7 +773,7 @@ insn_info::fledder (rtx set)
+ if (REG_P(mem))
+ src_mem_reg = mem;
+ else if (GET_CODE(mem) == CONST_INT)
+- src_intval = INTVAL(mem);
++ src_mem_addr = INTVAL(mem);
+ else if (GET_CODE(mem) == SYMBOL_REF)
+ src_symbol = mem;
+ else if (GET_CODE(mem) == PLUS)
+@@ -749,7 +785,7 @@ insn_info::fledder (rtx set)
+ {
+ src_mem_reg = reg;
+ src_const = true;
+- src_intval = INTVAL(konst);
++ src_mem_addr = INTVAL(konst);
+ }
+ }
+ else if (GET_CODE(mem) == CONST)
+@@ -762,7 +798,7 @@ insn_info::fledder (rtx set)
+ {
+ src_plus = true;
+ src_symbol = sym;
+- src_intval = INTVAL(XEXP(mem, 1));
++ src_mem_addr = INTVAL(XEXP(mem, 1));
+ }
+ }
+ }
+@@ -770,7 +806,7 @@ insn_info::fledder (rtx set)
+ else if (GET_CODE(src) == CONST_INT)
+ {
+ src_const = true;
+- src_intval = INTVAL(src);
++ src_mem_addr = INTVAL(src);
+ }
+ else if (GET_CODE(src) == PLUS)
+ {
+@@ -783,7 +819,7 @@ insn_info::fledder (rtx set)
+ {
+ src_reg = reg;
+ src_const = true;
+- src_intval = INTVAL(konst);
++ src_mem_addr = INTVAL(konst);
+ }
+ else if (REG_P(konst))
+ {
+@@ -915,6 +951,42 @@ insn_info::swap_adds (rtx_insn * newinsn, insn_info & ii)
+ // usage flags did not change
+ }
+
++static
++void
++replace_reg (rtx x, unsigned regno, rtx newreg, int offset)
++{
++ RTX_CODE code = GET_CODE(x);
++ const char *fmt = GET_RTX_FORMAT(code);
++ for (int i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
++ {
++ if (fmt[i] == 'e')
++ {
++ rtx y = XEXP(x, i);
++ if (REG_P(y) && REGNO(y) == regno)
++ {
++ XEXP(x, i) = newreg;
++ if (offset && i + 1 < GET_RTX_LENGTH(code))
++ {
++ rtx c = XEXP(x, i + 1);
++ if (GET_CODE(c) == CONST_INT)
++ XEXP(x, i + 1) = gen_rtx_CONST_INT (GET_MODE(x), INTVAL(c) + offset);
++ }
++ }
++ else
++ replace_reg (y, regno, newreg, offset);
++ }
++ else if (fmt[i] == 'E')
++ for (int j = XVECLEN (x, i) - 1; j >= 0; j--)
++ replace_reg (XVECEXP(x, i, j), regno, newreg, offset);
++ }
++}
++
++void
++insn_info::a5_to_a7 (rtx a7)
++{
++ replace_reg (PATTERN (insn), FRAME_POINTER_REGNUM, a7, -4);
++}
++
+ void
+ insn_info::set_insn (rtx_insn * newinsn)
+ {
+@@ -923,32 +995,63 @@ insn_info::set_insn (rtx_insn * newinsn)
+ }
+
+ void
+-insn_info::absolute2base (unsigned regno, unsigned base)
++insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol)
+ {
+ rtx set = PATTERN (get_insn ());
+ rtx src = SET_SRC(set);
+- machine_mode mode = GET_MODE(SET_DEST(set));
+-
+- unsigned addr = get_dst_addr ();
+- unsigned offset = addr - base;
++ rtx dst = SET_DEST(set);
++ machine_mode mode = GET_MODE(dst);
+
+ rtx pattern;
+ rtx reg = gen_raw_REG (SImode, regno);
+- if (base == addr)
+- pattern = gen_rtx_SET(gen_rtx_MEM (mode, reg), src);
+- else
+- pattern = gen_rtx_SET(gen_rtx_MEM (mode, gen_rtx_PLUS(SImode, reg, gen_rtx_CONST_INT(SImode, offset))), src);
++
++ if (is_dst_mem () && (has_dst_addr () || get_dst_symbol ()) && !has_dst_memreg () && get_dst_symbol () == with_symbol)
++ {
++ unsigned addr = get_dst_addr ();
++ unsigned offset = addr - base;
++ if (offset <= 0x7ffe)
++ {
++ rtx olddst = dst;
++ if (base == addr)
++ dst = gen_rtx_MEM (mode, reg);
++ else
++ dst = gen_rtx_MEM (mode, gen_rtx_PLUS(SImode, reg, gen_rtx_CONST_INT (SImode, offset)));
++
++ if (src_plus && rtx_equal_p (olddst, XEXP(src, 0)))
++ XEXP(src, 0) = dst;
++
++ dst_mem_reg = reg;
++ dst_mem = true;
++ dst_mem_addr = offset;
++ dst_plus = offset != 0;
++ }
++ }
++
++ if (is_src_mem () && (has_src_addr () || get_src_symbol ()) && !has_src_memreg () && get_src_symbol () == with_symbol)
++ {
++ unsigned addr = get_src_addr ();
++ unsigned offset = addr - base;
++ if (offset <= 0x7ffe)
++ {
++ if (base == addr)
++ src = gen_rtx_MEM (mode, reg);
++ else
++ src = gen_rtx_MEM (mode, gen_rtx_PLUS(SImode, reg, gen_rtx_CONST_INT (SImode, offset)));
++
++ src_mem_reg = reg;
++ src_mem = true;
++ src_mem_addr = offset;
++ src_plus = offset != 0;
++ }
++ }
++
++ pattern = gen_rtx_SET(dst, src);
+
+ SET_INSN_DELETED(insn);
+ insn = emit_insn_after (pattern, insn);
+
+ mark_use (regno);
+
+- dst_mem_reg = reg;
+- dst_mem = true;
+- dst_mem_addr = offset;
+- dst_plus = offset != 0;
+-
+ insn2index.insert (std::make_pair (insn, this));
+ }
+ /*
+@@ -2646,29 +2749,29 @@ opt_shrink_stack_frame (void)
+
+ if (usea5 && a5offset == -4)
+ {
++ /* for now only drop the frame pointer if it's not used.
++ * Needs tracking of the sp to adjust the offsets.
++ */
+ if (freemask & (1 << FRAME_POINTER_REGNUM))
+ {
+ log ("dropping unused frame pointer\n");
+- for (std::vector<int>::iterator i = a5pos.begin (); i != a5pos.end (); ++i)
+- SET_INSN_DELETED(infos[*i].get_insn ());
++ for (auto i = a5pos.rbegin (); i != a5pos.rend (); ++i)
++ {
++ SET_INSN_DELETED(infos[*i].get_insn ());
++ infos.erase (infos.begin () + *i);
++ }
+
+- /* convert parameter access via a5 into a7. */
++ /* convert all parameter accesses via a5 into a7. */
+ for (unsigned i = 0; i < infos.size (); ++i)
+ {
+ insn_info & ii = infos[i];
++ if (ii.get_myuse () & (1 << FRAME_POINTER_REGNUM))
++ ii.a5_to_a7 (a7);
+
+- if (ii.is_dst_reg () && ii.get_src_mem_regno () == FRAME_POINTER_REGNUM)
+- {
+- rtx x = gen_rtx_CONST_INT (SImode, ii.get_src_intval () - 4);
+- rtx p = gen_rtx_PLUS(SImode, a7, x);
+- rtx pattern = gen_rtx_SET(copy_reg (ii.get_dst_reg (), -1),
+- gen_rtx_MEM (GET_MODE(ii.get_dst_reg ()), p));
+- set_insn_deleted (ii.get_insn ());
+- rtx_insn * newinsn = emit_insn_after (pattern, ii.get_insn ());
+- ii.plus_to_move (newinsn);
+- }
++ ii.unset (FRAME_POINTER_REGNUM);
+ }
+
++ update_insn2index ();
+ ++changed;
+ }
+ }
+@@ -2687,18 +2790,23 @@ opt_absolute (void)
+ for (unsigned i = 0; i < infos.size (); ++i)
+ {
+ insn_info & ii = infos[i];
+- if (!ii.is_dst_mem () || !ii.has_dst_addr () || ii.has_dst_memreg ())
++
++ bool is_dst = ii.is_dst_mem () && (ii.has_dst_addr () || ii.get_dst_symbol ()) && !ii.has_dst_memreg ();
++ bool is_src = ii.is_src_mem () && (ii.has_src_addr () || ii.get_src_symbol ()) && !ii.has_src_memreg ();
++
++ if (!is_dst && !is_src)
+ continue;
+
+ unsigned freemask = ~(ii.get_use () | ii.get_def ()) & 0x7f00 & usable_regs;
+ if (!freemask)
+ continue;
+
+- rtx with_symbol = ii.get_dst_symbol ();
++ rtx with_symbol = is_dst ? ii.get_dst_symbol () : ii.get_src_symbol ();
+
+ std::vector<unsigned> found;
+ found.push_back (i);
+ unsigned base = ii.get_dst_addr ();
++ unsigned max = base;
+ unsigned j = i + 1;
+ for (; j < infos.size (); ++j)
+ {
+@@ -2710,13 +2818,49 @@ opt_absolute (void)
+ if (!freemask)
+ break;
+
+- if (jj.is_dst_mem () && jj.has_dst_addr () && !jj.has_dst_memreg () && jj.get_dst_symbol () == with_symbol)
++ bool j_dst = jj.is_dst_mem () && (jj.has_dst_addr () || jj.get_dst_symbol ()) && !jj.has_dst_memreg ()
++ && jj.get_dst_symbol () == with_symbol;
++ bool j_src = jj.is_src_mem () && (jj.has_src_addr () || jj.get_src_symbol ()) && !jj.has_src_memreg ()
++ && jj.get_src_symbol () == with_symbol;
++ if (j_dst)
+ {
+ unsigned addr = jj.get_dst_addr ();
+ if (addr < base)
+- base = addr;
+-
+- found.push_back (j);
++ {
++ if (max - addr <= 0x7ffe)
++ {
++ base = addr;
++ found.push_back (j);
++ continue;
++ }
++ }
++ else if (addr - base <= 0x7ffe)
++ {
++ if (addr > max)
++ max = addr;
++ found.push_back (j);
++ continue;
++ }
++ }
++ if (j_src)
++ {
++ unsigned addr = jj.get_src_addr ();
++ if (addr < base)
++ {
++ if (max - addr <= 0x7ffe)
++ {
++ base = addr;
++ found.push_back (j);
++ continue;
++ }
++ }
++ else if (addr - base <= 0x7ffe)
++ {
++ if (addr > max)
++ max = addr;
++ found.push_back (j);
++ continue;
++ }
+ }
+ }
+
+@@ -2743,7 +2887,7 @@ opt_absolute (void)
+ for (auto k = found.begin (); k != found.end (); ++k)
+ {
+ insn_info & kk = infos[*k];
+- kk.absolute2base (regno, base);
++ kk.absolute2base (regno, base, with_symbol);
+ }
+
+ // load base into reg
+@@ -2767,13 +2911,17 @@ opt_absolute (void)
+ nn.fledder (lea);
+ nn.mark_def (regno);
+ infos.insert (infos.begin () + i, nn);
+- while (i++ < j)
+- infos[i].mark_use (regno);
+- ++j;
++
++ /* mark until last hit is found. */
++ for (unsigned k = i + 1; k < infos.size (); ++k)
++ {
++ infos[k].mark_use (regno);
++ if (k == *found.rbegin ())
++ break;
++ }
+ ++change_count;
++ --i;
+ }
+-
+- i = j;
+ }
+
+ if (change_count)
+
+From 6e6ca44d77a0ac430aaa9d55181fada079ad76d1 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 4 May 2017 14:59:26 +0200
+Subject: [PATCH 110/303] @B fix cmp_sub
+
+---
+ gcc/bbb-opts.c | 15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index a4bb1e0a97a3..568ce2a6543d 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -2192,14 +2192,17 @@ opt_const_cmp_to_sub (void)
+
+ rtx jmppattern = PATTERN (patchme);
+
+- rtx jmpsrc = XEXP(jmppattern, 1);
+- if (!jmpsrc)
++ if (GET_RTX_LENGTH (GET_CODE(jmppattern)) < 2)
+ ok = false;
+- else if (GET_CODE(jmpsrc) == IF_THEN_ELSE)
++ else
+ {
+- rtx condition = XEXP(jmpsrc, 0);
+- RTX_CODE code = GET_CODE(condition);
+- ok = code == EQ || code == NE;
++ rtx jmpsrc = XEXP(jmppattern, 1);
++ if (GET_CODE(jmpsrc) == IF_THEN_ELSE)
++ {
++ rtx condition = XEXP(jmpsrc, 0);
++ RTX_CODE code = GET_CODE(condition);
++ ok = code == EQ || code == NE;
++ }
+ }
+ }
+ }
+
+From bcacd054f6a8b47c7fa16580697a23fc0cd3393b Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 4 May 2017 22:59:56 +0200
+Subject: [PATCH 111/303] @R opt_cmp_sub is now capable to replace a chain of
+ compares
+
+---
+ .cproject | 4 +
+ gcc/bbb-opts.c | 243 +++++++++++++++++++++++++++++++++------------------------
+ 2 files changed, 145 insertions(+), 102 deletions(-)
+
+diff --git a/.cproject b/.cproject
+index b3cddaefb27b..6db4cbe2447e 100755
+--- .cproject
++++ .cproject
+@@ -43,6 +43,7 @@
+ <listOptionValue builtIn="false" value="IN_GCC=1"/>
+ <listOptionValue builtIn="false" value="HAVE_cc0=1"/>
+ <listOptionValue builtIn="false" value="__ECLIPSE__=1"/>
++ <listOptionValue builtIn="false" value="TARGET_AMIGA=1"/>
+ </option>
+ <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.cygwin.780175803" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input.cygwin"/>
+ </tool>
+@@ -58,6 +59,7 @@
+ <listOptionValue builtIn="false" value="IN_GCC=1"/>
+ <listOptionValue builtIn="false" value="HAVE_cc0=1"/>
+ <listOptionValue builtIn="false" value="__ECLIPSE__=1"/>
++ <listOptionValue builtIn="false" value="TARGET_AMIGA=1"/>
+ </option>
+ <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.cygwin.2078467313" superClass="cdt.managedbuild.tool.gnu.c.compiler.input.cygwin"/>
+ </tool>
+@@ -106,6 +108,7 @@
+ <listOptionValue builtIn="false" value="IN_GCC=1"/>
+ <listOptionValue builtIn="false" value="HAVE_cc0=1"/>
+ <listOptionValue builtIn="false" value="__ECLIPSE__=1"/>
++ <listOptionValue builtIn="false" value="TARGET_AMIGA=1"/>
+ </option>
+ <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1150724656" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+ </tool>
+@@ -119,6 +122,7 @@
+ <listOptionValue builtIn="false" value="IN_GCC=1"/>
+ <listOptionValue builtIn="false" value="HAVE_cc0=1"/>
+ <listOptionValue builtIn="false" value="__ECLIPSE__=1"/>
++ <listOptionValue builtIn="false" value="TARGET_AMIGA=1"/>
+ </option>
+ <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1133865092" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+ </tool>
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 568ce2a6543d..0d8ecedc7941 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -183,6 +183,18 @@ class insn_info
+ void
+ absolute2base (unsigned regno, unsigned base, rtx with_symbol);
+
++ inline bool
++ is_compare () const
++ {
++ return compare;
++ }
++
++ inline machine_mode
++ get_mode () const
++ {
++ return mode;
++ }
++
+ inline bool
+ is_dst_reg () const
+ {
+@@ -387,6 +399,29 @@ class insn_info
+ hard = 0;
+ }
+
++ inline void
++ reset_flags ()
++ {
++ compare = false;
++ dst_mem = false;
++ src_mem = false;
++ dst_plus = false;
++ src_plus = false;
++ src_const = false;
++
++ mode = VOIDmode;
++
++ dst_reg = 0;
++ dst_mem_reg = 0;
++ dst_symbol = 0;
++ src_reg = 0;
++ src_mem_reg = 0;
++ src_symbol = 0;
++ dst_mem_addr = 0;
++
++ src_mem_addr = 0;
++ }
++
+ inline bool
+ is_empty ()
+ {
+@@ -711,8 +746,6 @@ insn_info::fledder (rtx set)
+ rtx dst = SET_DEST(set);
+ rtx src = SET_SRC(set);
+
+- mode = GET_MODE(dst);
+-
+ if (dst == cc0_rtx)
+ {
+ compare = true;
+@@ -721,6 +754,8 @@ insn_info::fledder (rtx set)
+ src = SET_SRC(set);
+ }
+
++ mode = GET_MODE(dst);
++
+ if (REG_P(dst))
+ {
+ dst_reg = dst;
+@@ -991,6 +1026,9 @@ void
+ insn_info::set_insn (rtx_insn * newinsn)
+ {
+ insn = newinsn;
++
++ reset_flags ();
++
+ fledder (PATTERN (insn));
+ }
+
+@@ -1255,7 +1293,7 @@ update_insn_infos (void)
+
+ /* fill the mask of general used regs. */
+ insn_info zz;
+- for (int i = 0; i < infos.size (); ++i)
++ for (unsigned i = 0; i < infos.size (); ++i)
+ {
+ insn_info & ii = infos[i];
+ if (ii.in_proepi () != 1)
+@@ -2097,140 +2135,141 @@ opt_const_cmp_to_sub (void)
+ {
+ unsigned change_count = 0;
+ #if HAVE_cc0
+- for (int index = infos.size () - 2; index > 0; --index)
++ if (infos.size () < 2)
++ return change_count;
++
++ unsigned lastsub = 0;
++ for (unsigned index = infos.size () - 2; index > 0; --index)
+ {
+- rtx_insn * insn = infos[index].get_insn ();
+- rtx seti = single_set (insn);
+- if (!seti)
++ insn_info & i1 = infos[index];
++
++ /* we wan't a compare or tst insn, */
++ if (!i1.is_compare ())
+ continue;
+
+- rtx dsti = SET_DEST(seti);
+- if (dsti != cc0_rtx)
++ if (GET_MODE_SIZE(i1.get_mode()) > 4 || !i1.is_dst_reg () || REGNO(i1.get_dst_reg()) > 7)
+ continue;
+
+- rtx srci = SET_SRC(seti);
+- if (GET_CODE(srci) != COMPARE)
++ /* src must be a reg dead register with a constant - or a #0 */
++ if (!i1.get_src_reg () && (!i1.is_src_const () || i1.is_src_plus ()))
+ continue;
+
+- rtx left = XEXP(srci, 0);
+- rtx right = XEXP(srci, 1);
+- if (!REG_P(left) || !REG_P(right) || REG_NREGS(left) > 1 || REG_NREGS(right) > 1)
++ /* allow an alive reg, if life ends at previous handled sub. */
++ int lastsubval = 0;
++ if (lastsub == index + 3)
++ {
++ insn_info & pp = infos[lastsub];
++ if (pp.get_dst_regno () != i1.get_dst_regno ())
++ continue;
++ lastsubval = pp.get_src_intval ();
++ }
++ else if (!is_reg_dead (i1.get_dst_regno (), index))
+ continue;
+
+- // TODO
+- // FEATURE: check if the next uses are also a add/sub
+- // then maybe that add/sub can be adjusted too
++ insn_info & i0 = infos[index - 1];
++ int intval = 0;
++ /* compare with register - check previous insn for load with constant. */
++ if (i1.is_src_reg ())
++ {
++ if (!is_reg_dead (i1.get_src_regno (), index))
++ continue;
+
+-// if (!find_reg_note (insn, REG_DEAD, left) || !find_reg_note (insn, REG_DEAD, right))
+-// continue;
+- /* use own reg_dead - reg_notes seem to be inaccurate!? */
+- if (!is_reg_dead (REGNO(left), index) || !is_reg_dead (REGNO(right), index))
+- continue;
++ if (GET_MODE_SIZE(i0.get_mode()) > 4)
++ continue;
+
+- // maybe add a search?
+- rtx_insn * prev = infos[index - 1].get_insn ();
+- rtx setp = single_set (prev);
+- if (!setp)
+- continue;
++ if (!i0.is_dst_reg () && (!i0.is_src_const () || i0.is_src_plus ()))
++ continue;
+
+- rtx constant_reg = SET_DEST(setp);
+- if (!REG_P(constant_reg))
+- continue;
++ if (i0.get_dst_regno () != i1.get_src_regno ())
++ continue;
+
+- rtx srcp = SET_SRC(setp);
+- if (!CONST_INT_P(srcp))
+- continue;
++ intval = -i0.get_src_intval ();
++ if (intval < -8 || intval > 7)
++ continue;
+
+- int intval = -INTVAL(srcp);
+- if (intval < -8 || intval > 7 || intval == 0)
+- continue;
++ /* is the next sub value in range? */
++ if (lastsub == index + 3 && (lastsubval - intval < -8 || lastsubval - intval > 7))
++ continue;
++ }
+
+- enum machine_mode mode = GET_MODE(constant_reg);
+- if (GET_MODE_SIZE(mode) > 4)
++ /* next insn must be the jump. */
++ insn_info & i2 = infos[index + 1];
++ if (!i2.is_jump ())
+ continue;
+
+- // printf("mode size: %d\n", GET_MODE_SIZE(mode));
++ rtx_insn * jump = i2.get_insn ();
++ rtx jmppattern = PATTERN (jump);
++ if (GET_RTX_LENGTH (GET_CODE(jmppattern)) < 2)
++ continue;
+
+- rtx reg = constant_reg == left ? right : constant_reg == right ? left : 0;
++ rtx jmpsrc = XEXP(jmppattern, 1);
++ if (GET_CODE(jmpsrc) != IF_THEN_ELSE)
++ continue;
+
+- // no gain with address regs.
+- if (!reg || REGNO(reg) > 7)
++ rtx condition = XEXP(jmpsrc, 0);
++ RTX_CODE code = GET_CODE(condition);
++ if (code != EQ && code != NE)
+ continue;
+
+- // search the jump(s)
+- bool ok = true;
++ if (intval)
+ {
+- // invert all conditions using this statement.
+- std::vector<unsigned> todo;
+- std::vector<unsigned> done;
+- done.resize (infos.size ());
+- todo.push_back (index + 1);
++ rtx copyreg = copy_reg (i1.get_dst_reg (), -1);
++ /* create the sub statement. */
++ rtx sub = gen_rtx_PLUS(i1.get_mode (), copyreg, gen_rtx_CONST_INT (i1.get_mode (), intval));
+
+- while (ok && todo.size ())
+- {
+- unsigned pos = todo[todo.size () - 1];
+- todo.pop_back ();
++ rtx_insn * subinsn = make_insn_raw (gen_rtx_SET(copyreg, sub));
+
+- if (done[pos])
+- continue;
++ int num_clobbers_to_add = 0;
++ int insn_code_number = recog (PATTERN (subinsn), subinsn, &num_clobbers_to_add);
++ if (insn_code_number < 0 || !check_asm_operands (PATTERN (subinsn)))
++ continue;
+
+- done[pos] = 1;
++ /* delete move #x,dy. */
++ SET_INSN_DELETED(i0.get_insn ())
++ /* delete cmp dx,dy */
++ SET_INSN_DELETED(i1.get_insn ());
++ /* add a cmp #0 - to be removed in final() */
+
+- if (infos[pos].is_def (FIRST_PSEUDO_REGISTER))
+- continue;
++ /* convert cmp/tst into sub */
++ subinsn = emit_insn_before (PATTERN (subinsn), i1.get_insn ());
++ i1.set_insn (subinsn);
+
+- if (pos + 1 < infos.size ())
+- todo.push_back (pos + 1);
++ rtx neu = gen_rtx_SET(cc0_rtx,
++ gen_rtx_COMPARE(i1.get_mode (), copyreg, gen_rtx_CONST_INT(i1.get_mode (), 0)));
+
+- rtx_insn * patchme = infos[pos].get_insn ();
+- if (!JUMP_P(patchme))
+- continue;
++ emit_insn_before (neu, i2.get_insn ());
+
+- auto j = insn2index.find ((rtx_insn *) JUMP_LABEL(patchme));
+- if (j != insn2index.end ())
+- todo.push_back (j->second->get_index ());
++ log ("const_cmp_to_sub replaced %s == %s (%d) with sub %d,%s\n", reg_names[i1.get_dst_regno ()],
++ reg_names[i0.get_dst_regno ()],
++ -intval, -intval, reg_names[i1.get_dst_regno ()]);
+
+- rtx jmppattern = PATTERN (patchme);
++ if (index + 3 == lastsub)
++ {
++ /* patch previous sub - or even a compare. */
++ insn_info & pp = infos[lastsub];
++
++ int diff = lastsubval - intval;
++ rtx c = gen_rtx_CONST_INT (i1.get_mode (), diff);
+
+- if (GET_RTX_LENGTH (GET_CODE(jmppattern)) < 2)
+- ok = false;
++ if (pp.is_compare ())
++ {
++ /* still a compare with 0 -> insert the sub. */
++ rtx copyreg = copy_reg (i1.get_dst_reg (), -1);
++ /* create the sub statement. */
++ rtx sub = gen_rtx_PLUS(i1.get_mode (), copyreg, c);
++ rtx set = gen_rtx_SET(copyreg, sub);
++ emit_insn_before (set, pp.get_insn ());
++ }
+ else
+ {
+- rtx jmpsrc = XEXP(jmppattern, 1);
+- if (GET_CODE(jmpsrc) == IF_THEN_ELSE)
+- {
+- rtx condition = XEXP(jmpsrc, 0);
+- RTX_CODE code = GET_CODE(condition);
+- ok = code == EQ || code == NE;
+- }
++ /* modify the sub. */
++ XEXP(SET_SRC(PATTERN(pp.get_insn())), 1) = c;
+ }
+ }
+- }
+- if (!ok)
+- continue;
+-
+- rtx plus = gen_rtx_PLUS(mode, copy_reg (reg, -1), gen_rtx_CONST_INT (mode, intval));
+
+- rtx_insn * neuprev = make_insn_raw (gen_rtx_SET(copy_reg (reg, -1), plus));
+-
+- int num_clobbers_to_add = 0;
+- int insn_code_number = recog (PATTERN (neuprev), neuprev, &num_clobbers_to_add);
+- if (insn_code_number < 0 || !check_asm_operands (PATTERN (neuprev)))
+- continue;
+-
+- // also convert current statement to cmp #0, reg
+- SET_INSN_DELETED(insn);
+- rtx copyreg = copy_reg (reg, -1);
+- rtx neu = gen_rtx_SET(cc0_rtx, gen_rtx_COMPARE(mode, copyreg, gen_rtx_CONST_INT(mode, 0)));
+- insn = emit_insn_after (neu, prev);
+- add_reg_note (insn, REG_DEAD, copyreg);
+-
+- SET_INSN_DELETED(prev);
+- prev = emit_insn_before (PATTERN (neuprev), insn);
+-
+- log ("const_cmp_to_sub replaced reg-reg compare with sub\n");
+-
+- ++change_count;
++ lastsub = index;
++ ++change_count;
++ }
+ }
+ #endif
+ return change_count;
+@@ -2992,7 +3031,7 @@ namespace
+ pass_bbb_optimizations::execute_bbb_optimizations (void)
+ {
+ be_very_verbose = strchr (string_bbb_opts, 'V');
+- be_verbose = be_very_verbose || strchr (string_bbb_opts, 'v') || 1;
++ be_verbose = be_very_verbose || strchr (string_bbb_opts, 'v');
+
+ bool do_opt_strcpy = strchr (string_bbb_opts, 's') || strchr (string_bbb_opts, '+');
+ bool do_commute_add_move = strchr (string_bbb_opts, 'a') || strchr (string_bbb_opts, '+');
+
+From 92278608b8be02dd6fc699e0ea912e12e3047a23 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 7 May 2017 17:50:45 +0200
+Subject: [PATCH 112/303] @B opt_absolute now only touches insns with a valid
+ mode.
+
+---
+ gcc/bbb-opts.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 0d8ecedc7941..e6ff270e8837 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -755,6 +755,8 @@ insn_info::fledder (rtx set)
+ }
+
+ mode = GET_MODE(dst);
++ if (mode == VOIDmode)
++ mode = GET_MODE(src);
+
+ if (REG_P(dst))
+ {
+@@ -1038,7 +1040,6 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol)
+ rtx set = PATTERN (get_insn ());
+ rtx src = SET_SRC(set);
+ rtx dst = SET_DEST(set);
+- machine_mode mode = GET_MODE(dst);
+
+ rtx pattern;
+ rtx reg = gen_raw_REG (SImode, regno);
+@@ -2839,6 +2840,9 @@ opt_absolute (void)
+ if (!is_dst && !is_src)
+ continue;
+
++ if (ii.get_mode() == VOIDmode)
++ continue;
++
+ unsigned freemask = ~(ii.get_use () | ii.get_def ()) & 0x7f00 & usable_regs;
+ if (!freemask)
+ continue;
+@@ -2860,6 +2864,9 @@ opt_absolute (void)
+ if (!freemask)
+ break;
+
++ if (jj.get_mode() == VOIDmode)
++ continue;
++
+ bool j_dst = jj.is_dst_mem () && (jj.has_dst_addr () || jj.get_dst_symbol ()) && !jj.has_dst_memreg ()
+ && jj.get_dst_symbol () == with_symbol;
+ bool j_src = jj.is_src_mem () && (jj.has_src_addr () || jj.get_src_symbol ()) && !jj.has_src_memreg ()
+
+From 1e4de684a62e18bcb9655cbc1029c24dd426fcb5 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 9 May 2017 19:40:17 +0200
+Subject: [PATCH 113/303] @R be more compatible to different gcc versions
+
+replaced auto with explicite types
+---
+ gcc/bbb-opts.c | 21 ++++++++++++---------
+ 1 file changed, 12 insertions(+), 9 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 0d8ecedc7941..c1e3f247335f 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -923,6 +923,9 @@ temp_reg_rename (std::vector<std::pair<rtx *, rtx> > & loc, rtx x, unsigned oldr
+ static std::vector<insn_info> infos;
+ static std::vector<rtx_insn *> jumps;
+ static std::map<rtx_insn *, insn_info *> insn2index;
++typedef std::vector<insn_info>::iterator insn_info_iterator;
++typedef std::vector<rtx_insn *>::iterator rtx_insn_iterator;
++typedef std::map<rtx_insn *, insn_info *>::iterator i2i_iterator;
+
+ static insn_info * info0;
+ static unsigned usable_regs;
+@@ -1130,7 +1133,7 @@ void
+ append_reg_usage (FILE * f, rtx_insn * insn)
+ {
+
+- auto i = insn2index.find (insn);
++ i2i_iterator i = insn2index.find (insn);
+ if (i == insn2index.end ())
+ return;
+
+@@ -1238,11 +1241,11 @@ update_insn_infos (void)
+ if (LABEL_P(insn))
+ {
+ /* work on all jumps referring to that label. */
+- for (auto i = jumps.begin (); i != jumps.end (); ++i)
++ for (rtx_insn_iterator i = jumps.begin (); i != jumps.end (); ++i)
+ {
+ if (JUMP_LABEL(*i) == insn)
+ {
+- auto j = insn2index.find (*i);
++ i2i_iterator j = insn2index.find (*i);
+ if (j != insn2index.end ())
+ todo.push_back (std::make_pair (j->second->get_index (), ii));
+ }
+@@ -1481,11 +1484,11 @@ opt_reg_rename (void)
+ * check if the reg was used at that jump.
+ * if used, find def
+ */
+- for (auto i = jumps.begin (); i != jumps.end (); ++i)
++ for (rtx_insn_iterator i = jumps.begin (); i != jumps.end (); ++i)
+ {
+ if (JUMP_LABEL(*i) == insn)
+ {
+- auto j = insn2index.find (*i);
++ i2i_iterator j = insn2index.find (*i);
+ if (j == insn2index.end ())
+ continue;
+
+@@ -1528,7 +1531,7 @@ opt_reg_rename (void)
+ /* follow jump and/or next insn. */
+ if (JUMP_P(insn))
+ {
+- auto j = insn2index.find ((rtx_insn *) JUMP_LABEL(insn));
++ i2i_iterator j = insn2index.find ((rtx_insn *) JUMP_LABEL(insn));
+ if (j == insn2index.end ())
+ {
+ /* whoops - label not found. */
+@@ -2797,7 +2800,7 @@ opt_shrink_stack_frame (void)
+ if (freemask & (1 << FRAME_POINTER_REGNUM))
+ {
+ log ("dropping unused frame pointer\n");
+- for (auto i = a5pos.rbegin (); i != a5pos.rend (); ++i)
++ for (std::vector<int>::reverse_iterator i = a5pos.rbegin (); i != a5pos.rend (); ++i)
+ {
+ SET_INSN_DELETED(infos[*i].get_insn ());
+ infos.erase (infos.begin () + *i);
+@@ -2909,7 +2912,7 @@ opt_absolute (void)
+ if (freemask && found.size () > 2)
+ {
+ /* check again. */
+- for (auto k = found.begin (); k != found.end ();)
++ for (std::vector<unsigned>::iterator k = found.begin (); k != found.end ();)
+ {
+ insn_info & kk = infos[*k];
+ if (kk.get_dst_addr () - base > 0x7ffc)
+@@ -2926,7 +2929,7 @@ opt_absolute (void)
+ else
+ log ("modifying %d absolute addresses using %s\n", found.size (), reg_names[regno]);
+
+- for (auto k = found.begin (); k != found.end (); ++k)
++ for (std::vector<unsigned>::iterator k = found.begin (); k != found.end (); ++k)
+ {
+ insn_info & kk = infos[*k];
+ kk.absolute2base (regno, base, with_symbol);
+
+From 3625786a260599ad20349b8bd22cc88ad90fecb0 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 12 May 2017 22:17:41 +0200
+Subject: [PATCH 114/303] @I remove eclipse specific defines
+
+---
+ gcc/bbb-opts.c | 9 ---------
+ 1 file changed, 9 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index c1e3f247335f..77e7f71f3b47 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -74,15 +74,6 @@
+ bool be_very_verbose;
+ bool be_verbose;
+
+-#ifdef __ECLIPSE__
+-//extern char * string_bbb_opts;
+-#define FIRST_PSEUDO_REGISTER 25
+-#define FRAME_POINTER_REGNUM 13
+-#define STACK_POINTER_REGNUM 15
+-#define NOTICE_UPDATE_CC(a,b)
+-#define Pmode SImode
+-#define PIC_REG 12
+-#endif
+ extern struct lang_hooks lang_hooks;
+
+ /* Lookup of the current function name. */
+
+From e43aec51a54659db8760159c651a27b4efb88580 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sat, 13 May 2017 23:06:49 +0200
+Subject: [PATCH 115/303] @B avoid lea into data regs - enforce constraints
+
+---
+ gcc/config/m68k/constraints.md | 6 ++++++
+ gcc/config/m68k/m68k.md | 8 ++++----
+ 2 files changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/config/m68k/constraints.md b/gcc/config/m68k/constraints.md
+index b62120895304..94a785dc95b6 100644
+--- gcc/config/m68k/constraints.md
++++ gcc/config/m68k/constraints.md
+@@ -97,6 +97,12 @@
+ (match_test "!TARGET_PCREL")
+ (match_test "!flag_pic || LEGITIMATE_PIC_OPERAND_P (op)")))
+
++(define_constraint "t"
++ "Used for operands that satisfy 's' without PIC stuff, when -mpcrel is not in effect."
++ (and (match_code "symbol_ref,label_ref,const")
++ (match_test "!TARGET_PCREL")
++ (match_test "!flag_pic || GET_CODE(op) != CONST || GET_CODE (XEXP (op, 0)) == SYMBOL_REF || GET_CODE (XEXP (op, 0)) == LABEL_REF")))
++
+ (define_memory_constraint "Q"
+ "Means address register indirect addressing mode."
+ (and (match_code "mem")
+diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
+index 24332476b91b..d5ab0cfab8c8 100644
+--- gcc/config/m68k/m68k.md
++++ gcc/config/m68k/m68k.md
+@@ -955,8 +955,8 @@
+ (define_insn "*movsi_m68k"
+ ;; Notes: make sure no alternative allows g vs g.
+ ;; We don't allow f-regs since fixed point cannot go in them.
+- [(set (match_operand:SI 0 "nonimmediate_operand" "=g,d,a<")
+- (match_operand:SI 1 "general_src_operand" "damSnT,n,i"))]
++ [(set (match_operand:SI 0 "nonimmediate_operand" "=g,a,d,a<")
++ (match_operand:SI 1 "general_src_operand" "damSnt,T,n,i"))]
+ "!TARGET_COLDFIRE && reload_completed"
+ {
+ return output_move_simode (operands);
+@@ -966,8 +966,8 @@
+ ;; force integer constants in range for a moveq to be reloaded
+ ;; if they are headed for memory.
+ (define_insn "*movsi_m68k2"
+- [(set (match_operand:SI 0 "nonimmediate_operand" "=g,d,a<")
+- (match_operand:SI 1 "general_src_operand" "damSKT,n,i"))]
++ [(set (match_operand:SI 0 "nonimmediate_operand" "=g,a,d,a<")
++ (match_operand:SI 1 "general_src_operand" "damSKt,T,n,i"))]
+
+ "!TARGET_COLDFIRE"
+ {
+
+From 4a3f28381185450e2ceeafa657032690420a66ab Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sat, 13 May 2017 23:07:46 +0200
+Subject: [PATCH 116/303] @B use fresh insns instead of modifying old ones in
+ opt_strcpy()
+
+---
+ gcc/bbb-opts.c | 16 ++++------------
+ 1 file changed, 4 insertions(+), 12 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index e6ff270e8837..f4dfb6177260 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -1963,8 +1963,8 @@ opt_strcpy ()
+ int num_clobbers_to_add = 0;
+ int insn_code_number;
+
+- rtx_insn * newinsn = make_insn_raw (
+- gen_rtx_SET(SET_DEST(single_set(reg2x)), SET_SRC(single_set (x2reg))));
++ rtx pattern = gen_rtx_SET(SET_DEST(single_set(reg2x)), SET_SRC(single_set (x2reg)));
++ rtx_insn * newinsn = make_insn_raw (pattern);
+ insn_code_number = recog (PATTERN (newinsn), newinsn, &num_clobbers_to_add);
+ if (insn_code_number >= 0 && check_asm_operands (PATTERN (newinsn)))
+ {
+@@ -1973,18 +1973,10 @@ opt_strcpy ()
+ log ("opt_strcpy condition met, removing compare and joining insns - omit reg %s\n",
+ reg_names[REGNO(dst)]);
+
+- SET_SRC(single_set(reg2x)) = SET_SRC(single_set (x2reg));
+-
+- for (link = REG_NOTES(x2reg); link; link = XEXP(link, 1))
+- if (REG_NOTE_KIND (link) != REG_LABEL_OPERAND)
+- {
+- if (GET_CODE (link) == EXPR_LIST)
+- add_reg_note (reg2x, REG_NOTE_KIND(link), copy_insn_1 (XEXP(link, 0)));
+- else
+- add_shallow_copy_of_reg_note (reg2x, link);
+- }
++ emit_insn_after(pattern, reg2x);
+
+ SET_INSN_DELETED(x2reg);
++ SET_INSN_DELETED(reg2x);
+ SET_INSN_DELETED(insn);
+
+ ++change_count;
+
+From 03bac6a165016f2c667087d2f5102d2bc2cb897c Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sat, 13 May 2017 23:34:25 +0200
+Subject: [PATCH 117/303] @B exclude some operations and compares in
+ opt_absolute()
+
+---
+ gcc/bbb-opts.c | 22 +++++++++++++++++++++-
+ 1 file changed, 21 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index f4dfb6177260..ff7532281630 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -2826,6 +2826,9 @@ opt_absolute (void)
+ {
+ insn_info & ii = infos[i];
+
++ if (ii.is_compare())
++ continue;
++
+ bool is_dst = ii.is_dst_mem () && (ii.has_dst_addr () || ii.get_dst_symbol ()) && !ii.has_dst_memreg ();
+ bool is_src = ii.is_src_mem () && (ii.has_src_addr () || ii.get_src_symbol ()) && !ii.has_src_memreg ();
+
+@@ -2839,6 +2842,14 @@ opt_absolute (void)
+ if (!freemask)
+ continue;
+
++ rtx pattern = PATTERN(ii.get_insn());
++ if (is_dst && !ii.get_src_reg() && !ii.is_src_const())
++ if (MEM_P(XEXP(XEXP(pattern, 1), 0)))
++ continue;
++ if (is_src && !ii.get_dst_reg())
++ if (MEM_P(XEXP(XEXP(pattern, 0), 0)))
++ continue;
++
+ rtx with_symbol = is_dst ? ii.get_dst_symbol () : ii.get_src_symbol ();
+
+ std::vector<unsigned> found;
+@@ -2856,13 +2867,22 @@ opt_absolute (void)
+ if (!freemask)
+ break;
+
+- if (jj.get_mode() == VOIDmode)
++ if (jj.get_mode() == VOIDmode || jj.is_compare())
+ continue;
+
+ bool j_dst = jj.is_dst_mem () && (jj.has_dst_addr () || jj.get_dst_symbol ()) && !jj.has_dst_memreg ()
+ && jj.get_dst_symbol () == with_symbol;
+ bool j_src = jj.is_src_mem () && (jj.has_src_addr () || jj.get_src_symbol ()) && !jj.has_src_memreg ()
+ && jj.get_src_symbol () == with_symbol;
++
++ pattern = PATTERN(jj.get_insn());
++ if (j_dst && !jj.get_src_reg() && !jj.is_src_const())
++ if (MEM_P(XEXP(XEXP(pattern, 1), 0)))
++ continue;
++ if (j_src && !jj.get_dst_reg())
++ if (MEM_P(XEXP(XEXP(pattern, 0), 0)))
++ continue;
++
+ if (j_dst)
+ {
+ unsigned addr = jj.get_dst_addr ();
+
+From 9e1dd52e9e1bdb1ca9af945c5853b9d5b3a9fb46 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 15 May 2017 11:06:25 +0200
+Subject: [PATCH 118/303] @B fix #20: handle subrge/strict_low_part in (b)
+
+---
+ gcc/DATESTAMP | 2 +-
+ gcc/bbb-opts.c | 103 +++++++++++++++++++++++++++++++--------------------------
+ 2 files changed, 58 insertions(+), 47 deletions(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 59aff9a1ff47..2f2212531db5 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170430
++20170515
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index ff7532281630..ebae14f41832 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -148,6 +148,7 @@ class insn_info
+ bool src_mem;
+ bool dst_plus;
+ bool src_plus;
++ int src_op;
+ bool src_const;
+
+ machine_mode mode;
+@@ -165,7 +166,7 @@ class insn_info
+ public:
+ insn_info (rtx_insn * i = 0, int p = 0) :
+ insn (i), myuse (0), hard (0), use (0), def (0), proepi (p), stack (false), label (false), jump (false), call (
+- false), compare (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus (false), src_const (
++ false), compare (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus (false), src_op (0), src_const (
+ false), mode (VOIDmode), dst_reg (0), dst_mem_reg (0), dst_symbol (0), src_reg (0), src_mem_reg (0), src_symbol (
+ 0), dst_mem_addr (0), src_mem_addr (0)
+ {
+@@ -281,13 +282,13 @@ class insn_info
+ inline bool
+ is_src_reg () const
+ {
+- return src_reg && !src_plus;
++ return src_reg && !src_op;
+ }
+
+- inline bool
+- is_src_plus () const
++ inline int
++ get_src_op () const
+ {
+- return src_reg && src_plus;
++ return src_op;
+ }
+
+ inline bool
+@@ -407,6 +408,7 @@ class insn_info
+ src_mem = false;
+ dst_plus = false;
+ src_plus = false;
++ src_op = 0;
+ src_const = false;
+
+ mode = VOIDmode;
+@@ -754,6 +756,9 @@ insn_info::fledder (rtx set)
+ src = SET_SRC(set);
+ }
+
++ if (GET_CODE(dst) == STRICT_LOW_PART || GET_CODE(dst) == SUBREG)
++ dst = XEXP(dst, 0);
++
+ mode = GET_MODE(dst);
+ if (mode == VOIDmode)
+ mode = GET_MODE(src);
+@@ -845,22 +850,26 @@ insn_info::fledder (rtx set)
+ src_const = true;
+ src_mem_addr = INTVAL(src);
+ }
+- else if (GET_CODE(src) == PLUS)
++ /* It' some kind of operation, e.g. PLUS, XOR, NEG, ... */
++ if (*GET_RTX_FORMAT(GET_CODE(src)) == 'e')
+ {
+- src_plus = true;
++ src_op = GET_CODE(src);
+ rtx reg = XEXP(src, 0);
+- rtx konst = XEXP(src, 1);
+- if (REG_P(reg))
++ if (REG_P(reg) && GET_RTX_LENGTH(GET_CODE(src)) >= 2)
+ {
+- if (GET_CODE(konst) == CONST_INT)
++ rtx konst = XEXP(src, 1);
++ src_reg = reg;
++ if (konst)
+ {
+- src_reg = reg;
+- src_const = true;
+- src_mem_addr = INTVAL(konst);
+- }
+- else if (REG_P(konst))
+- {
+- src_reg = konst;
++ if (GET_CODE(konst) == CONST_INT)
++ {
++ src_const = true;
++ src_mem_addr = INTVAL(konst);
++ }
++ else if (REG_P(konst))
++ {
++ src_reg = konst; /* dst_reg = dst_reg OP src_reg: store src_reg not dst_reg */
++ }
+ }
+ }
+ }
+@@ -969,7 +978,7 @@ void
+ insn_info::plus_to_move (rtx_insn * newinsn)
+ {
+ insn = newinsn;
+- src_plus = false;
++ src_op = 0;
+ src_reg = XEXP(PATTERN (newinsn), 1);
+ insn2index.insert (std::make_pair (insn, this));
+ // usage flags did not change
+@@ -1603,7 +1612,7 @@ opt_reg_rename (void)
+ if (!ok)
+ continue;
+
+- log ("opt_reg_rename %s -> %s (%d locs, start at %d)\n", reg_names[oldregno], reg_names[newregno],
++ log ("(r) opt_reg_rename %s -> %s (%d locs, start at %d)\n", reg_names[oldregno], reg_names[newregno],
+ patch.size (), index);
+
+ /* apply all changes. */
+@@ -1846,7 +1855,7 @@ opt_propagate_moves ()
+ rtx_insn * after = infos[index + 1].get_insn ();
+ rtx bset = single_set (before);
+
+- log ("propagate_moves condition met, moving regs %s, %s\n",
++ log ("(p) propagate_moves condition met, moving regs %s, %s\n",
+ reg_names[REGNO(srci)],
+ reg_names[REGNO(dsti)]);
+
+@@ -1882,7 +1891,7 @@ opt_propagate_moves ()
+ /* add fixes if there were jumps out of the loop. */
+ if (jump_out.size ())
+ {
+- log ("propagate_moves fixing %d jump outs\n", jump_out.size ());
++ log ("(p) propagate_moves fixing %d jump outs\n", jump_out.size ());
+
+ for (unsigned k = 0; k < jump_out.size (); ++k)
+ {
+@@ -1970,10 +1979,10 @@ opt_strcpy ()
+ {
+ rtx link;
+
+- log ("opt_strcpy condition met, removing compare and joining insns - omit reg %s\n",
++ log ("(s) opt_strcpy condition met, removing compare and joining insns - omit reg %s\n",
+ reg_names[REGNO(dst)]);
+
+- emit_insn_after(pattern, reg2x);
++ emit_insn_after (pattern, reg2x);
+
+ SET_INSN_DELETED(x2reg);
+ SET_INSN_DELETED(reg2x);
+@@ -2086,7 +2095,7 @@ opt_commute_add_move (void)
+
+ if (validate_change (next, &SET_DEST(set2), newmem, 0))
+ {
+- log ("commute_add_move found\n");
++ log ("(a) commute_add_move found\n");
+
+ SET_INSN_DELETED(insn);
+
+@@ -2144,7 +2153,7 @@ opt_const_cmp_to_sub (void)
+ continue;
+
+ /* src must be a reg dead register with a constant - or a #0 */
+- if (!i1.get_src_reg () && (!i1.is_src_const () || i1.is_src_plus ()))
++ if (!i1.get_src_reg () && (!i1.is_src_const () || i1.get_src_op () == PLUS))
+ continue;
+
+ /* allow an alive reg, if life ends at previous handled sub. */
+@@ -2170,7 +2179,7 @@ opt_const_cmp_to_sub (void)
+ if (GET_MODE_SIZE(i0.get_mode()) > 4)
+ continue;
+
+- if (!i0.is_dst_reg () && (!i0.is_src_const () || i0.is_src_plus ()))
++ if (!i0.is_dst_reg () && (!i0.is_src_const () || i0.get_src_op () == PLUS))
+ continue;
+
+ if (i0.get_dst_regno () != i1.get_src_regno ())
+@@ -2232,7 +2241,7 @@ opt_const_cmp_to_sub (void)
+
+ emit_insn_before (neu, i2.get_insn ());
+
+- log ("const_cmp_to_sub replaced %s == %s (%d) with sub %d,%s\n", reg_names[i1.get_dst_regno ()],
++ log ("(c) const_cmp_to_sub replaced %s == %s (%d) with sub %d,%s\n", reg_names[i1.get_dst_regno ()],
+ reg_names[i0.get_dst_regno ()],
+ -intval, -intval, reg_names[i1.get_dst_regno ()]);
+
+@@ -2293,7 +2302,7 @@ opt_elim_dead_assign (void)
+
+ if (is_reg_dead (REGNO(dst), index))
+ {
+- log ("%d: elim_dead_assign to %s\n", index, reg_names[REGNO(dst)]);
++ log ("(e) %d: elim_dead_assign to %s\n", index, reg_names[REGNO(dst)]);
+ SET_INSN_DELETED(insn);
+ ++change_count;
+ }
+@@ -2333,7 +2342,7 @@ opt_merge_add (void)
+ continue;
+ }
+
+- if (!ii0.is_dst_reg () || !ii0.is_src_plus () || !ii1.is_src_plus () || !ii2.is_src_plus ())
++ if (!ii0.is_dst_reg () || ii0.get_src_op () != PLUS || ii1.get_src_op () != PLUS || ii2.get_src_op () != PLUS)
+ continue;
+
+ if (!ii0.is_src_const () || !ii2.is_src_const () || ii0.get_src_intval () != ii2.get_src_intval ())
+@@ -2349,7 +2358,7 @@ opt_merge_add (void)
+ if (cc_status.value1 || cc_status.value2)
+ continue;
+
+- log ("%d: merge_add applied\n", index);
++ log ("(m) %d: merge_add applied\n", index);
+
+ rtx_insn * insn0 = ii0.get_insn ();
+ rtx set = PATTERN (insn0);
+@@ -2610,7 +2619,7 @@ opt_shrink_stack_frame (void)
+ unsigned regbit = 1 << REGNO(reg);
+ if (freemask & regbit)
+ {
+- log (i < prologueend ? "remove push for %s\n" : "remove pop for %s\n",
++ log (i < prologueend ? "(f) remove push for %s\n" : "(f) remove pop for %s\n",
+ reg_names[REGNO(reg)]);
+ if (i < prologueend)
+ adjust += 4;
+@@ -2631,7 +2640,7 @@ opt_shrink_stack_frame (void)
+ int add1 = i < prologueend || !usea5 ? 1 : 0;
+ if ((int) regs.size () + add1 < XVECLEN(pattern, 0) || regs.size () <= 2)
+ {
+- log ("shrinking stack frame from %d to %d\n", XVECLEN(pattern, 0) - add1, regs.size ());
++ log ("(f) shrinking stack frame from %d to %d\n", XVECLEN(pattern, 0) - add1, regs.size ());
+ if (regs.size () <= 2)
+ {
+ changed = 1;
+@@ -2726,7 +2735,7 @@ opt_shrink_stack_frame (void)
+ if (freemask & regbit)
+ {
+ adjust += REGNO(src) > STACK_POINTER_REGNUM ? 12 : 4;
+- log ("remove push for %s\n", reg_names[REGNO(src)]);
++ log ("(f) remove push for %s\n", reg_names[REGNO(src)]);
+ SET_INSN_DELETED(insn);
+ ++changed;
+ }
+@@ -2738,7 +2747,7 @@ opt_shrink_stack_frame (void)
+ unsigned regbit = 1 << REGNO(dst);
+ if (freemask & regbit)
+ {
+- log ("remove pop for %s\n", reg_names[REGNO(dst)]);
++ log ("(f) remove pop for %s\n", reg_names[REGNO(dst)]);
+ SET_INSN_DELETED(insn);
+ ++changed;
+ }
+@@ -2789,7 +2798,7 @@ opt_shrink_stack_frame (void)
+ */
+ if (freemask & (1 << FRAME_POINTER_REGNUM))
+ {
+- log ("dropping unused frame pointer\n");
++ log ("(f) dropping unused frame pointer\n");
+ for (auto i = a5pos.rbegin (); i != a5pos.rend (); ++i)
+ {
+ SET_INSN_DELETED(infos[*i].get_insn ());
+@@ -2826,7 +2835,7 @@ opt_absolute (void)
+ {
+ insn_info & ii = infos[i];
+
+- if (ii.is_compare())
++ if (ii.is_compare ())
+ continue;
+
+ bool is_dst = ii.is_dst_mem () && (ii.has_dst_addr () || ii.get_dst_symbol ()) && !ii.has_dst_memreg ();
+@@ -2835,18 +2844,19 @@ opt_absolute (void)
+ if (!is_dst && !is_src)
+ continue;
+
+- if (ii.get_mode() == VOIDmode)
++ if (ii.get_mode () == VOIDmode)
+ continue;
+
+ unsigned freemask = ~(ii.get_use () | ii.get_def ()) & 0x7f00 & usable_regs;
+ if (!freemask)
+ continue;
+
+- rtx pattern = PATTERN(ii.get_insn());
+- if (is_dst && !ii.get_src_reg() && !ii.is_src_const())
++ /* exclude operations on that symbol. */
++ rtx pattern = PATTERN (ii.get_insn ());
++ if (is_dst && !ii.get_src_reg () && !ii.is_src_const ())
+ if (MEM_P(XEXP(XEXP(pattern, 1), 0)))
+ continue;
+- if (is_src && !ii.get_dst_reg())
++ if (is_src && !ii.get_dst_reg ())
+ if (MEM_P(XEXP(XEXP(pattern, 0), 0)))
+ continue;
+
+@@ -2867,7 +2877,7 @@ opt_absolute (void)
+ if (!freemask)
+ break;
+
+- if (jj.get_mode() == VOIDmode || jj.is_compare())
++ if (jj.get_mode () == VOIDmode || jj.is_compare ())
+ continue;
+
+ bool j_dst = jj.is_dst_mem () && (jj.has_dst_addr () || jj.get_dst_symbol ()) && !jj.has_dst_memreg ()
+@@ -2875,11 +2885,12 @@ opt_absolute (void)
+ bool j_src = jj.is_src_mem () && (jj.has_src_addr () || jj.get_src_symbol ()) && !jj.has_src_memreg ()
+ && jj.get_src_symbol () == with_symbol;
+
+- pattern = PATTERN(jj.get_insn());
+- if (j_dst && !jj.get_src_reg() && !jj.is_src_const())
++ /* exclude operations on that symbol. */
++ pattern = PATTERN (jj.get_insn ());
++ if (j_dst && !jj.get_src_reg () && !jj.is_src_const ())
+ if (MEM_P(XEXP(XEXP(pattern, 1), 0)))
+ continue;
+- if (j_src && !jj.get_dst_reg())
++ if (j_src && !jj.get_dst_reg ())
+ if (MEM_P(XEXP(XEXP(pattern, 0), 0)))
+ continue;
+
+@@ -2941,9 +2952,9 @@ opt_absolute (void)
+ {
+ unsigned regno = bit2regno (freemask);
+ if (with_symbol)
+- log ("modifying %d symbol addresses using %s\n", found.size (), reg_names[regno]);
++ log ("(b) modifying %d symbol addresses using %s\n", found.size (), reg_names[regno]);
+ else
+- log ("modifying %d absolute addresses using %s\n", found.size (), reg_names[regno]);
++ log ("(b) modifying %d absolute addresses using %s\n", found.size (), reg_names[regno]);
+
+ for (auto k = found.begin (); k != found.end (); ++k)
+ {
+
+From 7ad7dde941ed115c07b25ab998132282014b7141 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 15 May 2017 15:45:41 +0200
+Subject: [PATCH 119/303] @R undo a stack frame change - no longer needed
+
+---
+ gcc/config/m68k/m68k.c | 8 +++-----
+ 1 file changed, 3 insertions(+), 5 deletions(-)
+
+diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
+index 8a40cbc2ab1f..3b51b2541bc9 100644
+--- gcc/config/m68k/m68k.c
++++ gcc/config/m68k/m68k.c
+@@ -808,11 +808,9 @@ m68k_compute_frame_layout (void)
+
+ /* Only compute the frame once per function.
+ Don't cache information until reload has been completed. */
+- /* SBF: No. Register renaming may free some variables,
+- * => compute it again and again... */
+-// if (current_frame.funcdef_no == current_function_funcdef_no
+-// && reload_completed)
+-// return;
++ if (current_frame.funcdef_no == current_function_funcdef_no
++ && reload_completed)
++ return;
+
+ current_frame.size = (get_frame_size () + 3) & -4;
+
+
+From 06d5805ee8035c3f8e32d7a14fb764bfbd9c2d83 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 15 May 2017 18:06:54 +0200
+Subject: [PATCH 120/303] @B fix #19 - fix stack frame shrinking bugs
+
+---
+ gcc/bbb-opts.c | 100 ++++++++++++++++++++++++++++++++-------------------------
+ 1 file changed, 56 insertions(+), 44 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index ebae14f41832..a997d721d605 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -88,10 +88,10 @@ extern struct lang_hooks lang_hooks;
+ /* Lookup of the current function name. */
+ extern tree current_function_decl;
+ static tree last_function_decl;
++static char fxname[512];
+ static char const *
+ get_current_function_name ()
+ {
+- static char fxname[512];
+ if (current_function_decl == NULL)
+ strcpy (fxname, "<toplevel>");
+ else
+@@ -297,6 +297,12 @@ class insn_info
+ return src_mem && src_plus;
+ }
+
++ inline bool
++ is_dst_mem_plus () const
++ {
++ return dst_mem && dst_plus;
++ }
++
+ inline int
+ get_dst_regno () const
+ {
+@@ -327,12 +333,24 @@ class insn_info
+ return src_mem_reg ? REGNO(src_mem_reg) : -1;
+ }
+
++ inline int
++ get_dst_mem_regno () const
++ {
++ return dst_mem_reg ? REGNO(dst_mem_reg) : -1;
++ }
++
+ inline int
+ get_src_intval () const
+ {
+ return src_mem_addr;
+ }
+
++ inline int
++ get_dst_intval () const
++ {
++ return dst_mem_addr;
++ }
++
+ inline bool
+ is_src_const () const
+ {
+@@ -2587,6 +2605,12 @@ opt_shrink_stack_frame (void)
+ /* check the pushed regs, either a vector or single statements */
+ if (GET_CODE(pattern) == PARALLEL)
+ {
++ // do not touch the frame pointer parallel insn.
++ rtx set = XVECEXP(pattern, 0, 0);
++ rtx dst = SET_DEST(set);
++ if (REG_P(dst) && REGNO(dst) == FRAME_POINTER_REGNUM)
++ continue;
++
+ std::vector<rtx> regs;
+ std::vector<rtx> clobbers;
+ for (int j = 0; j < XVECLEN(pattern, 0); ++j)
+@@ -2607,13 +2631,6 @@ opt_shrink_stack_frame (void)
+ else
+ continue;
+
+- if (REGNO(reg) == FRAME_POINTER_REGNUM)
+- {
+- // mark as "do not touch"
+- clobbers.push_back (reg);
+- break;
+- }
+-
+ if (i < prologueend)
+ paramstart += 4;
+ unsigned regbit = 1 << REGNO(reg);
+@@ -2628,19 +2645,16 @@ opt_shrink_stack_frame (void)
+ regs.push_back (copy_reg (reg, -1));
+ }
+
+- /* don't touch - clobbers! */
+- if (clobbers.size ())
+- continue;
+-
+- /* add romm for add.
++ /* add room for add.
+ * push is always using -(a7) addressing.
+ * If a5 is used a movem offset(a5) is generated to pop saved registers..
+ * Otherwise a7 is used and with (a7)+ addressing.
+ */
+ int add1 = i < prologueend || !usea5 ? 1 : 0;
+- if ((int) regs.size () + add1 < XVECLEN(pattern, 0) || regs.size () <= 2)
++ if ((int) regs.size () + add1 + (int) clobbers.size () < XVECLEN(pattern, 0) || regs.size () <= 2)
+ {
+- log ("(f) shrinking stack frame from %d to %d\n", XVECLEN(pattern, 0) - add1, regs.size ());
++ log ("(f) shrinking stack frame from %d to %d\n", XVECLEN(pattern, 0) - add1 - clobbers.size (),
++ regs.size ());
+ if (regs.size () <= 2)
+ {
+ changed = 1;
+@@ -2674,17 +2688,19 @@ opt_shrink_stack_frame (void)
+ for (unsigned k = 0; k < regs.size (); ++k)
+ x += REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4;
+
++ unsigned l = 0;
+ /* no add if a5 is used with pop */
+ if (!usea5 || i < prologueend)
+ {
+ plus = gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, i < prologueend ? -x : x));
+- XVECEXP(parallel, 0, 0) = gen_rtx_SET(a7, plus);
++ XVECEXP(parallel, 0, l) = gen_rtx_SET(a7, plus);
++ ++l;
+ }
+
+ if (i >= prologueend)
+ x = usea5 ? -x : 0;
+
+- for (unsigned k = 0; k < regs.size (); ++k)
++ for (unsigned k = 0; k < regs.size (); ++k, ++l)
+ {
+ if (i < prologueend)
+ {
+@@ -2693,7 +2709,7 @@ opt_shrink_stack_frame (void)
+ x -= REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4;
+ rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, plus);
+ rtx set = gen_rtx_SET(mem, regs[k]);
+- XVECEXP(parallel, 0, k + 1) = set;
++ XVECEXP(parallel, 0, l) = set;
+ }
+ else
+ {
+@@ -2704,7 +2720,7 @@ opt_shrink_stack_frame (void)
+ plus = gen_rtx_PLUS(SImode, a5, gen_rtx_CONST_INT (SImode, a5offset + x));
+ rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, plus);
+ rtx set = gen_rtx_SET(regs[k], mem);
+- XVECEXP(parallel, 0, k) = set;
++ XVECEXP(parallel, 0, l) = set;
+ }
+ else
+ {
+@@ -2712,10 +2728,16 @@ opt_shrink_stack_frame (void)
+ x += REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4;
+ rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, plus);
+ rtx set = gen_rtx_SET(regs[k], mem);
+- XVECEXP(parallel, 0, k + 1) = set;
++ XVECEXP(parallel, 0, l) = set;
+ }
+ }
+ }
++
++ for (unsigned k = 0; k < clobbers.size (); ++k)
++ {
++ rtx clobber = clobbers[k];
++ XVECEXP(parallel, 0, l++) = clobber;
++ }
+ emit_insn_after (parallel, insn);
+ }
+ SET_INSN_DELETED(insn);
+@@ -2761,32 +2783,19 @@ opt_shrink_stack_frame (void)
+ for (unsigned index = 0; index < infos.size (); ++index)
+ {
+ insn_info & ii = infos[index];
+- insn = ii.get_insn ();
+- if (!insn || !INSN_P(insn))
+- continue;
+-
+- rtx set = single_set (insn);
+- if (!set)
+- continue;
++ rtx pattern = PATTERN (ii.get_insn ());
++ if (ii.is_compare ())
++ pattern = XEXP(pattern, 1);
++ if (ii.is_src_mem () && ii.is_src_mem_plus () && ii.get_src_mem_regno () == STACK_POINTER_REGNUM)
++ {
++ rtx plus = XEXP(XEXP(pattern, 1), 0);
++ XEXP(plus, 1) = gen_rtx_CONST_INT (SImode, ii.get_src_intval () - adjust);
++ }
+
+- rtx mem = SET_SRC(set);
+- if (MEM_P(mem))
++ if (ii.is_dst_mem () && ii.is_dst_mem_plus () && ii.get_dst_mem_regno () == STACK_POINTER_REGNUM)
+ {
+- rtx plus = XEXP(mem, 0);
+- if (GET_CODE(plus) == PLUS)
+- {
+- rtx sp = XEXP(plus, 0);
+- if (REG_P(sp) && REGNO(sp) == STACK_POINTER_REGNUM)
+- {
+- rtx c = XEXP(plus, 1);
+- if (CONST_INT_P(c))
+- {
+- int n = INTVAL(c);
+- if (n >= paramstart)
+- XEXP(plus, 1) = gen_rtx_CONST_INT (SImode, n - adjust);
+- }
+- }
+- }
++ rtx plus = XEXP(XEXP(pattern, 0), 0);
++ XEXP(plus, 1) = gen_rtx_CONST_INT (SImode, ii.get_dst_intval () - adjust);
+ }
+ }
+ }
+@@ -3073,6 +3082,9 @@ namespace
+ bool do_shrink_stack_frame = strchr (string_bbb_opts, 'f') || strchr (string_bbb_opts, '+');
+ bool do_absolute = strchr (string_bbb_opts, 'b') || strchr (string_bbb_opts, '+');
+
++ if (be_very_verbose)
++ log ("ENTER\n");
++
+ for (;;)
+ {
+ int done = 1;
+
+From 6599877df5f8d490fbbc29a2509dd10137ebb0b4 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 15 May 2017 22:20:22 +0200
+Subject: [PATCH 121/303] @B fix #19 - renaming single registers of a register
+ pair (long long) is a bad idea...
+
+---
+ gcc/bbb-opts.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index d0bef1dbc6dc..800f83ea40fe 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -649,6 +649,8 @@ class insn_info
+ unsigned
+ get_regbit () const
+ {
++ if (GET_MODE_SIZE(mode) > 4)
++ return 0;
+ return def & ~hard & ~use & 0x7fff;
+ }
+
+@@ -1539,6 +1541,13 @@ opt_reg_rename (void)
+ else if (!(jj.get_use () & rename_regbit))
+ break;
+
++ /* abort if some insn using this reg uses more than 1 reg. */
++ if ((jj.get_myuse() & rename_regbit) && GET_MODE_SIZE(jj.get_mode()) > 4)
++ {
++ mask = 0;
++ break;
++ }
++
+ /* update free regs. */
+ mask &= ~jj.get_use ();
+ mask &= ~jj.get_def ();
+
+From b35c1e12d6be7dfaf301801267ff558f6b149be5 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 16 May 2017 12:47:15 +0200
+Subject: [PATCH 122/303] @B fix recognition of asm function parameters
+
+---
+ gcc/BASE-VER | 2 +-
+ gcc/DATESTAMP | 2 +-
+ gcc/config/m68k/amigaos.c | 7 +++++++
+ gcc/config/m68k/amigaos.h | 20 --------------------
+ gcc/config/m68k/m68kamigaos.h | 18 ++++++++++++++++++
+ 5 files changed, 27 insertions(+), 22 deletions(-)
+
+diff --git a/gcc/BASE-VER b/gcc/BASE-VER
+index 76af0075384a..6352d5267189 100644
+--- gcc/BASE-VER
++++ gcc/BASE-VER
+@@ -1 +1 @@
+-6.3.1d
++6.3.1b
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 2f2212531db5..43cf3b2286b6 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170515
++20170516
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index 419d59dc3871..3bd99b5c6389 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -463,6 +463,13 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl)
+ DPRINTF(("1amigaos_init_cumulative_args %p -> %d\r\n", cum, cum->num_of_regs));
+ }
+
++
++int
++amigaos_function_arg_reg(unsigned regno)
++{
++ return mycum.regs_already_used & (1 << regno) != 0;
++}
++
+ /* Update the data in CUM to advance over an argument. */
+
+ void
+diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h
+index e2a2b4cc11f6..284328683c37 100644
+--- gcc/config/m68k/amigaos.h
++++ gcc/config/m68k/amigaos.h
+@@ -381,31 +381,11 @@ amigaos_prelink_hook((const char **)(LD1_ARGV), (STRIP))
+ /* Note: this is an extension of m68k_args */
+
+
+-/* A C type for declaring a variable that is used as the first
+- argument of `FUNCTION_ARG' and other related values. */
+-/* Max. number of data, address and float registers to be used for passing
+- integer, pointer and float arguments when TARGET_REGPARM.
+- It's 4, so d0-d3, a0-a3 and fp0-fp3 can be used. */
+-#undef AMIGAOS_MAX_REGPARM
+-#define AMIGAOS_MAX_REGPARM 4
+-
+-/* The default number of data, address and float registers to use when
+- user specified '-mregparm' switch, not '-mregparm=<value>' option. */
+-#undef AMIGAOS_DEFAULT_REGPARM
+-#define AMIGAOS_DEFAULT_REGPARM 2
+-
+-
+ #undef CLASS_MAX_NREGS
+ #define CLASS_MAX_NREGS(CLASS, MODE) \
+ ((CLASS) == FP_REGS ? GET_MODE_NUNITS (MODE) \
+ : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
+
+-/* 1 if N is a possible register number for function argument passing. */
+-#undef FUNCTION_ARG_REGNO_P
+-#define FUNCTION_ARG_REGNO_P(N) \
+- ((((int)N) >= 0 && (N) < AMIGAOS_MAX_REGPARM) \
+- || ((N) >= 8 && (N) < 8 + AMIGAOS_MAX_REGPARM) \
+- || (TARGET_68881 && (N) >= 16 && (N) < 16 + AMIGAOS_MAX_REGPARM))
+
+ /*
+ On the m68k, this is a structure:
+diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h
+index 3ca2cd666e7c..f636e397cfca 100644
+--- gcc/config/m68k/m68kamigaos.h
++++ gcc/config/m68k/m68kamigaos.h
+@@ -670,3 +670,21 @@ extern int amiga_is_const_pic_ref(const_rtx x);
+
+ #define EH_TABLES_CAN_BE_READ_ONLY 1
+
++
++/* Max. number of data, address and float registers to be used for passing
++ integer, pointer and float arguments when TARGET_REGPARM.
++ It's 4, so d0-d3, a0-a3 and fp0-fp3 can be used. */
++#undef AMIGAOS_MAX_REGPARM
++#define AMIGAOS_MAX_REGPARM 4
++
++/* The default number of data, address and float registers to use when
++ user specified '-mregparm' switch, not '-mregparm=<value>' option. */
++#undef AMIGAOS_DEFAULT_REGPARM
++#define AMIGAOS_DEFAULT_REGPARM 2
++
++/* 1 if N is a possible register number for function argument passing. */
++#undef FUNCTION_ARG_REGNO_P
++#define FUNCTION_ARG_REGNO_P(N) amigaos_function_arg_reg(N)
++
++extern int
++amigaos_function_arg_reg(unsigned regno);
+
+From 42f9687b3643a14d216c68b685a8b79f0e860c0e Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 16 May 2017 12:50:48 +0200
+Subject: [PATCH 123/303] @B fix recognition of asm function parameters
+
+---
+ gcc/config/m68k/amigaos.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index 3bd99b5c6389..9166b91a69eb 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -467,7 +467,7 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl)
+ int
+ amigaos_function_arg_reg(unsigned regno)
+ {
+- return mycum.regs_already_used & (1 << regno) != 0;
++ return (mycum.regs_already_used & (1 << regno)) != 0;
+ }
+
+ /* Update the data in CUM to advance over an argument. */
+
+From 97158247a4a2e85140f33ab30a1a8a8802744e64 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 17 May 2017 09:34:58 +0200
+Subject: [PATCH 124/303] @B analyse jump_tables for correct flow and register
+ usage analysis
+
+---
+ gcc/bbb-opts.c | 121 ++++++++++++++++++++++++++++++++++++++++++---------------
+ 1 file changed, 90 insertions(+), 31 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 800f83ea40fe..e49148416a43 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -943,10 +943,12 @@ temp_reg_rename (std::vector<std::pair<rtx *, rtx> > & loc, rtx x, unsigned oldr
+ * Collect some data.
+ */
+ static std::vector<insn_info> infos;
+-static std::vector<rtx_insn *> jumps;
+-static std::map<rtx_insn *, insn_info *> insn2index;
+ typedef std::vector<insn_info>::iterator insn_info_iterator;
+-typedef std::vector<rtx_insn *>::iterator rtx_insn_iterator;
++
++static std::multimap<int, rtx_insn *> label2jump;
++typedef std::multimap<int, rtx_insn *>::iterator l2j_iterator;
++
++static std::map<rtx_insn *, insn_info *> insn2index;
+ typedef std::map<rtx_insn *, insn_info *>::iterator i2i_iterator;
+
+ static insn_info * info0;
+@@ -1122,7 +1124,7 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol)
+ static void
+ clear (void)
+ {
+- jumps.clear ();
++ label2jump.clear ();
+ insn2index.clear ();
+ infos.clear ();
+ }
+@@ -1154,7 +1156,7 @@ void
+ append_reg_usage (FILE * f, rtx_insn * insn)
+ {
+
+- i2i_iterator i = insn2index.find (insn);
++ i2i_iterator i = insn2index.find (insn);
+ if (i == insn2index.end ())
+ return;
+
+@@ -1262,14 +1264,12 @@ update_insn_infos (void)
+ if (LABEL_P(insn))
+ {
+ /* work on all jumps referring to that label. */
+- for (rtx_insn_iterator i = jumps.begin (); i != jumps.end (); ++i)
++ for (l2j_iterator i = label2jump.find (insn->u2.insn_uid), k = i;
++ i != label2jump.end () && i->first == k->first; ++i)
+ {
+- if (JUMP_LABEL(*i) == insn)
+- {
+- i2i_iterator j = insn2index.find (*i);
+- if (j != insn2index.end ())
+- todo.push_back (std::make_pair (j->second->get_index (), ii));
+- }
++ i2i_iterator j = insn2index.find (i->second);
++ if (j != insn2index.end ())
++ todo.push_back (std::make_pair (j->second->get_index (), ii));
+ }
+ continue;
+ }
+@@ -1299,7 +1299,7 @@ update_insn_infos (void)
+ if (!use.is_def (FIRST_PSEUDO_REGISTER))
+ {
+ CC_STATUS_INIT;
+- NOTICE_UPDATE_CC (PATTERN (insn), insn);
++ NOTICE_UPDATE_CC(PATTERN (insn), insn);
+ if (cc_status.value1 || cc_status.value2)
+ use.mark_def (FIRST_PSEUDO_REGISTER);
+ }
+@@ -1340,10 +1340,13 @@ update_insn_infos (void)
+ /*
+ * Create a filtered view of insns - keep only those to work with.
+ */
+-static void
++static int
+ update_insns ()
+ {
+ rtx_insn *insn, *next;
++
++ rtx jump_table = 0;
++
+ clear ();
+
+ char inproepilogue = 1;
+@@ -1360,10 +1363,50 @@ update_insns ()
+
+ if (JUMP_P(insn))
+ {
+- jumps.push_back (insn);
+ inproepilogue = 0;
+
+ ii.mark_jump ();
++
++ rtx pattern = PATTERN (insn);
++ if (GET_CODE(pattern) == PARALLEL)
++ {
++ /*
++ * Use the jump_table_data and add all to the lookup
++ */
++ if (jump_table == 0)
++ {
++ // still allow complex if_then_else which are also in parallel
++ rtx ite = XVECEXP(insn, 0, 0);
++ if (XEXP(ite, 0) != pc_rtx || GET_CODE(XEXP(ite, 1)) != IF_THEN_ELSE)
++ {
++ debug_rtx(insn);
++ return 1; // do not optimize.
++ }
++ }
++ else
++ if (XEXP(jump_table, 0) != insn)
++ {
++ debug_rtx(insn);
++ return 2;
++ }
++
++ // -> jump_table_data
++ rtx table = PATTERN (XEXP(jump_table, 1));
++ for (int j = 0; j < XVECLEN(table, 1); ++j)
++ {
++ rtx ref = XVECEXP(table, 1, j);
++ rtx label = XEXP(ref, 0);
++ label2jump.insert (std::make_pair (label->u2.insn_uid, insn));
++ }
++
++ jump_table = 0;
++ }
++ else
++ {
++ rtx_insn * label = (rtx_insn *) JUMP_LABEL(insn);
++ label2jump.insert (std::make_pair (label->u2.insn_uid, insn));
++ }
++
+ }
+ else if (LABEL_P(insn))
+ {
+@@ -1378,6 +1421,16 @@ update_insns ()
+ rtx set = single_set (insn);
+ if (set)
+ ii.fledder (set);
++
++ for (rtx next, note = REG_NOTES(insn); note; note = next)
++ {
++ next = XEXP(note, 1);
++ if (REG_NOTE_KIND (note) == REG_LABEL_OPERAND)
++ {
++ jump_table = XEXP(note, 0);
++ }
++ }
++
+ }
+ }
+
+@@ -1392,6 +1445,8 @@ update_insns ()
+
+ update_insn2index ();
+ update_insn_infos ();
++
++ return 0;
+ }
+
+ /* convert the lowest set bit into a register number. */
+@@ -1505,21 +1560,19 @@ opt_reg_rename (void)
+ * check if the reg was used at that jump.
+ * if used, find def
+ */
+- for (rtx_insn_iterator i = jumps.begin (); i != jumps.end (); ++i)
++ for (l2j_iterator i = label2jump.find (insn->u2.insn_uid), k = i;
++ i != label2jump.end () && i->first == k->first; ++i)
+ {
+- if (JUMP_LABEL(*i) == insn)
+- {
+- i2i_iterator j = insn2index.find (*i);
+- if (j == insn2index.end ())
+- continue;
++ i2i_iterator j = insn2index.find (i->second);
++ if (j == insn2index.end ())
++ continue;
+
+- unsigned start = j->second->get_index ();
+- if (!infos[start].is_use (rename_regno))
+- continue;
++ unsigned start = j->second->get_index ();
++ if (!infos[start].is_use (rename_regno))
++ continue;
+
+- start = find_start (found, start, rename_regno);
+- todo.push_back (start);
+- }
++ start = find_start (found, start, rename_regno);
++ todo.push_back (start);
+ }
+ continue;
+ }
+@@ -1542,7 +1595,7 @@ opt_reg_rename (void)
+ break;
+
+ /* abort if some insn using this reg uses more than 1 reg. */
+- if ((jj.get_myuse() & rename_regbit) && GET_MODE_SIZE(jj.get_mode()) > 4)
++ if ((jj.get_myuse () & rename_regbit) && GET_MODE_SIZE(jj.get_mode()) > 4)
+ {
+ mask = 0;
+ break;
+@@ -1987,7 +2040,7 @@ opt_strcpy ()
+ if (REG_P(dst) && CONST_INT_P(src) && INTVAL(src) == 0 && is_reg_dead (REGNO(dst), index))
+ {
+ /* now check via NOTICE_UPDATE_CC*/
+- NOTICE_UPDATE_CC (PATTERN (reg2x), reg2x);
++ NOTICE_UPDATE_CC(PATTERN (reg2x), reg2x);
+ if (cc_status.flags == 0 && rtx_equal_p (dst, cc_status.value2))
+ {
+ int num_clobbers_to_add = 0;
+@@ -2375,7 +2428,7 @@ opt_merge_add (void)
+ rtx_insn * insn1 = ii1.get_insn ();
+
+ CC_STATUS_INIT;
+- NOTICE_UPDATE_CC (PATTERN (insn1), insn1);
++ NOTICE_UPDATE_CC(PATTERN (insn1), insn1);
+ if (cc_status.value1 || cc_status.value2)
+ continue;
+
+@@ -3091,7 +3144,13 @@ namespace
+ for (;;)
+ {
+ int done = 1;
+- update_insns ();
++ int r = update_insns ();
++ if (r)
++ {
++ if (be_verbose)
++ log("no bbb optimization code %d\n", r);
++ return 0;
++ }
+ if (do_opt_strcpy && opt_strcpy ())
+ done = 0, update_insns ();
+
+
+From d49f98c1822e1a810d81048c0082ebec69a5d66f Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 17 May 2017 11:12:25 +0200
+Subject: [PATCH 125/303] @B support if_then_else inside of parallel insns
+
+---
+ gcc/DATESTAMP | 2 +-
+ gcc/bbb-opts.c | 37 ++++++++++++++++++-------------------
+ 2 files changed, 19 insertions(+), 20 deletions(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 43cf3b2286b6..f9bb1bba46d4 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170516
++20170517
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index e49148416a43..7fa077167ef2 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -1375,30 +1375,32 @@ update_insns ()
+ */
+ if (jump_table == 0)
+ {
+- // still allow complex if_then_else which are also in parallel
+- rtx ite = XVECEXP(insn, 0, 0);
++ // still allow if_then_else inside a parallel insn
++ rtx ite = XVECEXP(pattern, 0, 0);
+ if (XEXP(ite, 0) != pc_rtx || GET_CODE(XEXP(ite, 1)) != IF_THEN_ELSE)
+ {
+- debug_rtx(insn);
++ debug_rtx (insn);
+ return 1; // do not optimize.
+ }
++ rtx_insn * label = (rtx_insn *) JUMP_LABEL(insn);
++ label2jump.insert (std::make_pair (label->u2.insn_uid, insn));
+ }
+- else
+- if (XEXP(jump_table, 0) != insn)
++ else if (XEXP(jump_table, 0) != insn)
+ {
+- debug_rtx(insn);
++ debug_rtx (insn);
+ return 2;
+ }
+-
+- // -> jump_table_data
+- rtx table = PATTERN (XEXP(jump_table, 1));
+- for (int j = 0; j < XVECLEN(table, 1); ++j)
++ else
+ {
+- rtx ref = XVECEXP(table, 1, j);
+- rtx label = XEXP(ref, 0);
+- label2jump.insert (std::make_pair (label->u2.insn_uid, insn));
++ // -> jump_table_data
++ rtx table = PATTERN (XEXP(jump_table, 1));
++ for (int j = 0; j < XVECLEN(table, 1); ++j)
++ {
++ rtx ref = XVECEXP(table, 1, j);
++ rtx label = XEXP(ref, 0);
++ label2jump.insert (std::make_pair (label->u2.insn_uid, insn));
++ }
+ }
+-
+ jump_table = 0;
+ }
+ else
+@@ -1433,8 +1435,7 @@ update_insns ()
+
+ }
+ }
+-
+- if (NOTE_P(insn))
++ else if (NOTE_P(insn))
+ {
+ if (NOTE_KIND(insn) == NOTE_INSN_PROLOGUE_END)
+ inproepilogue = 0;
+@@ -2051,8 +2052,6 @@ opt_strcpy ()
+ insn_code_number = recog (PATTERN (newinsn), newinsn, &num_clobbers_to_add);
+ if (insn_code_number >= 0 && check_asm_operands (PATTERN (newinsn)))
+ {
+- rtx link;
+-
+ log ("(s) opt_strcpy condition met, removing compare and joining insns - omit reg %s\n",
+ reg_names[REGNO(dst)]);
+
+@@ -3148,7 +3147,7 @@ namespace
+ if (r)
+ {
+ if (be_verbose)
+- log("no bbb optimization code %d\n", r);
++ log ("no bbb optimization code %d\n", r);
+ return 0;
+ }
+ if (do_opt_strcpy && opt_strcpy ())
+
+From 7c4335944b40ed8cac718f17a3492b543589c1e9 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 17 May 2017 13:44:06 +0200
+Subject: [PATCH 126/303] @B fix absolute optimization
+
+---
+ gcc/bbb-opts.c | 10 ++--------
+ 1 file changed, 2 insertions(+), 8 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 7fa077167ef2..adc21bf4e39e 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -1081,7 +1081,8 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol)
+ else
+ dst = gen_rtx_MEM (mode, gen_rtx_PLUS(SImode, reg, gen_rtx_CONST_INT (SImode, offset)));
+
+- if (src_plus && rtx_equal_p (olddst, XEXP(src, 0)))
++ /* some operation to the same value as dst. eg. eor #5,symbol+8 -> eor #5,8(ax) */
++ if (src_op && rtx_equal_p (olddst, XEXP(src, 0)))
+ XEXP(src, 0) = dst;
+
+ dst_mem_reg = reg;
+@@ -2950,13 +2951,6 @@ opt_absolute (void)
+ && jj.get_src_symbol () == with_symbol;
+
+ /* exclude operations on that symbol. */
+- pattern = PATTERN (jj.get_insn ());
+- if (j_dst && !jj.get_src_reg () && !jj.is_src_const ())
+- if (MEM_P(XEXP(XEXP(pattern, 1), 0)))
+- continue;
+- if (j_src && !jj.get_dst_reg ())
+- if (MEM_P(XEXP(XEXP(pattern, 0), 0)))
+- continue;
+
+ if (j_dst)
+ {
+
+From f89679a40f70cf28bfe2e5b9cec347b292df4d1c Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 17 May 2017 20:55:45 +0200
+Subject: [PATCH 127/303] @B fix reading insn like lea 1(a0),a1 - to extract
+ the correct source register
+
+---
+ gcc/bbb-opts.c | 49 +++++++++++++++++++++++++------------------------
+ 1 file changed, 25 insertions(+), 24 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index adc21bf4e39e..37fc9dbd01fc 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -815,6 +815,25 @@ insn_info::fledder (rtx set)
+ }
+ }
+
++ /* It' some kind of operation, e.g. PLUS, XOR, NEG, ... */
++ rtx alt_src_reg = 0;
++ int code = GET_CODE(src);
++ if (!REG_P(src) && !MEM_P(src) && code != CONST_INT && code != CONST && code != CONST_WIDE_INT && code != CONST_DOUBLE
++ && code != CONST_FIXED && code != CONST_STRING)
++ {
++ src_op = GET_CODE(src);
++ const char *fmt = GET_RTX_FORMAT(code);
++ if (fmt[0] == 'e' && fmt[1] == 'e')
++ {
++ rtx operand = XEXP(src, 1);
++ if (GET_CODE(operand) == CONST_INT)
++ src_const = true, src_mem_addr = INTVAL(operand);
++ else if (REG_P(operand))
++ alt_src_reg = operand;
++ }
++ src = XEXP(src, 0);
++ }
++
+ if (REG_P(src))
+ {
+ src_reg = src;
+@@ -861,29 +880,8 @@ insn_info::fledder (rtx set)
+ src_const = true;
+ src_mem_addr = INTVAL(src);
+ }
+- /* It' some kind of operation, e.g. PLUS, XOR, NEG, ... */
+- if (*GET_RTX_FORMAT(GET_CODE(src)) == 'e')
+- {
+- src_op = GET_CODE(src);
+- rtx reg = XEXP(src, 0);
+- if (REG_P(reg) && GET_RTX_LENGTH(GET_CODE(src)) >= 2)
+- {
+- rtx konst = XEXP(src, 1);
+- src_reg = reg;
+- if (konst)
+- {
+- if (GET_CODE(konst) == CONST_INT)
+- {
+- src_const = true;
+- src_mem_addr = INTVAL(konst);
+- }
+- else if (REG_P(konst))
+- {
+- src_reg = konst; /* dst_reg = dst_reg OP src_reg: store src_reg not dst_reg */
+- }
+- }
+- }
+- }
++ if (alt_src_reg)
++ src_reg = alt_src_reg;
+ }
+
+ /* create a copy for a reg. Optional specify a new register number. */
+@@ -2844,7 +2842,10 @@ opt_shrink_stack_frame (void)
+ pattern = XEXP(pattern, 1);
+ if (ii.is_src_mem () && ii.is_src_mem_plus () && ii.get_src_mem_regno () == STACK_POINTER_REGNUM)
+ {
+- rtx plus = XEXP(XEXP(pattern, 1), 0);
++ rtx src = XEXP(pattern, 1);
++ rtx plus = XEXP(src, 0);
++ if (ii.get_src_op ())
++ plus = XEXP(plus, 0);
+ XEXP(plus, 1) = gen_rtx_CONST_INT (SImode, ii.get_src_intval () - adjust);
+ }
+
+
+From aa46f14ae49b802ed71bc0fa238045089ede31da Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 17 May 2017 23:29:00 +0200
+Subject: [PATCH 128/303] @B fix operations on symbol/absolute are now
+ correctly converted int operations on address reg
+
+---
+ gcc/bbb-opts.c | 68 ++++++++++++++++++++++++++++++++++------------------------
+ 1 file changed, 40 insertions(+), 28 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 37fc9dbd01fc..5cce787b0d27 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -139,7 +139,8 @@ class insn_info
+ bool src_mem;
+ bool dst_plus;
+ bool src_plus;
+- int src_op;
++ rtx_code src_op;
++ bool src_ee;
+ bool src_const;
+
+ machine_mode mode;
+@@ -151,15 +152,15 @@ class insn_info
+ rtx src_mem_reg;
+ rtx src_symbol;
+ unsigned dst_mem_addr;
+-
++ int src_intval;
+ unsigned src_mem_addr;
+
+ public:
+ insn_info (rtx_insn * i = 0, int p = 0) :
+ insn (i), myuse (0), hard (0), use (0), def (0), proepi (p), stack (false), label (false), jump (false), call (
+- false), compare (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus (false), src_op (0), src_const (
+- false), mode (VOIDmode), dst_reg (0), dst_mem_reg (0), dst_symbol (0), src_reg (0), src_mem_reg (0), src_symbol (
+- 0), dst_mem_addr (0), src_mem_addr (0)
++ false), compare (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus (false), src_op (
++ (rtx_code) 0), src_ee (false), src_const (false), mode (VOIDmode), dst_reg (0), dst_mem_reg (0), dst_symbol (
++ 0), src_reg (0), src_mem_reg (0), src_symbol (0), dst_mem_addr (0), src_intval (0), src_mem_addr (0)
+ {
+ }
+
+@@ -265,7 +266,7 @@ class insn_info
+ }
+
+ inline unsigned
+- get_src_addr () const
++ get_src_mem_addr () const
+ {
+ return src_mem_addr;
+ }
+@@ -282,6 +283,12 @@ class insn_info
+ return src_op;
+ }
+
++ inline bool
++ is_src_ee () const
++ {
++ return src_ee;
++ }
++
+ inline bool
+ is_src_mem_plus () const
+ {
+@@ -333,7 +340,7 @@ class insn_info
+ inline int
+ get_src_intval () const
+ {
+- return src_mem_addr;
++ return src_intval;
+ }
+
+ inline int
+@@ -417,7 +424,8 @@ class insn_info
+ src_mem = false;
+ dst_plus = false;
+ src_plus = false;
+- src_op = 0;
++ src_op = (rtx_code)0;
++ src_ee = false;
+ src_const = false;
+
+ mode = VOIDmode;
+@@ -430,6 +438,7 @@ class insn_info
+ src_symbol = 0;
+ dst_mem_addr = 0;
+
++ src_intval = 0;
+ src_mem_addr = 0;
+ }
+
+@@ -818,16 +827,17 @@ insn_info::fledder (rtx set)
+ /* It' some kind of operation, e.g. PLUS, XOR, NEG, ... */
+ rtx alt_src_reg = 0;
+ int code = GET_CODE(src);
+- if (!REG_P(src) && !MEM_P(src) && code != CONST_INT && code != CONST && code != CONST_WIDE_INT && code != CONST_DOUBLE
++ if (!REG_P(src) && !MEM_P(src) && code != CONST_INT && code != CONST && code != CONST_WIDE_INT && code != CONST_DOUBLE
+ && code != CONST_FIXED && code != CONST_STRING)
+ {
+ src_op = GET_CODE(src);
+ const char *fmt = GET_RTX_FORMAT(code);
+ if (fmt[0] == 'e' && fmt[1] == 'e')
+ {
++ src_ee = true;
+ rtx operand = XEXP(src, 1);
+- if (GET_CODE(operand) == CONST_INT)
+- src_const = true, src_mem_addr = INTVAL(operand);
++ if (GET_CODE(operand) == CONST_INT || GET_CODE(operand) == CONST_WIDE_INT)
++ src_const = true, src_intval = INTVAL(operand);
+ else if (REG_P(operand))
+ alt_src_reg = operand;
+ }
+@@ -992,7 +1002,7 @@ void
+ insn_info::plus_to_move (rtx_insn * newinsn)
+ {
+ insn = newinsn;
+- src_op = 0;
++ src_op = (rtx_code)0;
+ src_reg = XEXP(PATTERN (newinsn), 1);
+ insn2index.insert (std::make_pair (insn, this));
+ // usage flags did not change
+@@ -1079,10 +1089,6 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol)
+ else
+ dst = gen_rtx_MEM (mode, gen_rtx_PLUS(SImode, reg, gen_rtx_CONST_INT (SImode, offset)));
+
+- /* some operation to the same value as dst. eg. eor #5,symbol+8 -> eor #5,8(ax) */
+- if (src_op && rtx_equal_p (olddst, XEXP(src, 0)))
+- XEXP(src, 0) = dst;
+-
+ dst_mem_reg = reg;
+ dst_mem = true;
+ dst_mem_addr = offset;
+@@ -1092,7 +1098,7 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol)
+
+ if (is_src_mem () && (has_src_addr () || get_src_symbol ()) && !has_src_memreg () && get_src_symbol () == with_symbol)
+ {
+- unsigned addr = get_src_addr ();
++ unsigned addr = get_src_mem_addr ();
+ unsigned offset = addr - base;
+ if (offset <= 0x7ffe)
+ {
+@@ -1101,6 +1107,15 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol)
+ else
+ src = gen_rtx_MEM (mode, gen_rtx_PLUS(SImode, reg, gen_rtx_CONST_INT (SImode, offset)));
+
++ /* some operation to the same value as dst. eg. eor #5,symbol+8 -> eor #5,8(ax) */
++ if (src_op)
++ {
++ if (src_ee)
++ src = gen_rtx_fmt_ee(src_op, mode, src, gen_rtx_CONST_INT (mode, src_intval));
++ else
++ src = gen_rtx_fmt_e(src_op, mode, src);
++ }
++
+ src_mem_reg = reg;
+ src_mem = true;
+ src_mem_addr = offset;
+@@ -2846,7 +2861,7 @@ opt_shrink_stack_frame (void)
+ rtx plus = XEXP(src, 0);
+ if (ii.get_src_op ())
+ plus = XEXP(plus, 0);
+- XEXP(plus, 1) = gen_rtx_CONST_INT (SImode, ii.get_src_intval () - adjust);
++ XEXP(plus, 1) = gen_rtx_CONST_INT (SImode, ii.get_src_mem_addr () - adjust);
+ }
+
+ if (ii.is_dst_mem () && ii.is_dst_mem_plus () && ii.get_dst_mem_regno () == STACK_POINTER_REGNUM)
+@@ -2904,6 +2919,9 @@ opt_absolute (void)
+ if (ii.is_compare ())
+ continue;
+
++ if (ii.get_src_op () && ii.is_src_ee () && !ii.get_src_intval ())
++ continue;
++
+ bool is_dst = ii.is_dst_mem () && (ii.has_dst_addr () || ii.get_dst_symbol ()) && !ii.has_dst_memreg ();
+ bool is_src = ii.is_src_mem () && (ii.has_src_addr () || ii.get_src_symbol ()) && !ii.has_src_memreg ();
+
+@@ -2917,15 +2935,6 @@ opt_absolute (void)
+ if (!freemask)
+ continue;
+
+- /* exclude operations on that symbol. */
+- rtx pattern = PATTERN (ii.get_insn ());
+- if (is_dst && !ii.get_src_reg () && !ii.is_src_const ())
+- if (MEM_P(XEXP(XEXP(pattern, 1), 0)))
+- continue;
+- if (is_src && !ii.get_dst_reg ())
+- if (MEM_P(XEXP(XEXP(pattern, 0), 0)))
+- continue;
+-
+ rtx with_symbol = is_dst ? ii.get_dst_symbol () : ii.get_src_symbol ();
+
+ std::vector<unsigned> found;
+@@ -2946,6 +2955,9 @@ opt_absolute (void)
+ if (jj.get_mode () == VOIDmode || jj.is_compare ())
+ continue;
+
++ if (jj.get_src_op () && jj.is_src_ee () && !jj.get_src_intval ())
++ continue;
++
+ bool j_dst = jj.is_dst_mem () && (jj.has_dst_addr () || jj.get_dst_symbol ()) && !jj.has_dst_memreg ()
+ && jj.get_dst_symbol () == with_symbol;
+ bool j_src = jj.is_src_mem () && (jj.has_src_addr () || jj.get_src_symbol ()) && !jj.has_src_memreg ()
+@@ -2975,7 +2987,7 @@ opt_absolute (void)
+ }
+ if (j_src)
+ {
+- unsigned addr = jj.get_src_addr ();
++ unsigned addr = jj.get_src_mem_addr ();
+ if (addr < base)
+ {
+ if (max - addr <= 0x7ffe)
+
+From edca4acf887636033d51096888e751820ef9718d Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 18 May 2017 00:00:26 +0200
+Subject: [PATCH 129/303] @B fix opt_absolute for SIGN_EXTEND (ext.*)
+
+---
+ gcc/bbb-opts.c | 20 ++++++++++++++++----
+ 1 file changed, 16 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 5cce787b0d27..dd2923873c1d 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -1113,7 +1113,14 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol)
+ if (src_ee)
+ src = gen_rtx_fmt_ee(src_op, mode, src, gen_rtx_CONST_INT (mode, src_intval));
+ else
+- src = gen_rtx_fmt_e(src_op, mode, src);
++ {
++ if (src_op == SIGN_EXTEND)
++ {
++ PUT_MODE_RAW(src, mode == SImode ? HImode : mode == HImode ? QImode : SImode);
++ src->call = 1;
++ }
++ src = gen_rtx_fmt_e(src_op, mode, src);
++ }
+ }
+
+ src_mem_reg = reg;
+@@ -2945,12 +2952,17 @@ opt_absolute (void)
+ for (; j < infos.size (); ++j)
+ {
+ insn_info & jj = infos[j];
+- if (jj.is_label () || jj.is_jump () || jj.is_call ())
++ /* TODO: continue also at jump target */
++ if (jj.is_jump())
++ continue;
++ /* TODO: check if label is visited only from jump targets from herein. then the label is ok. */
++ if (jj.is_label ())
+ break;
+
+- freemask &= ~(jj.get_use () | jj.get_def ());
+- if (!freemask)
++ unsigned tempmask = freemask & ~(jj.get_use () | jj.get_def ());
++ if (!tempmask)
+ break;
++ freemask = tempmask;
+
+ if (jj.get_mode () == VOIDmode || jj.is_compare ())
+ continue;
+
+From 90e72be90df0d966c935ae3c91476af65f18cb81 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sat, 20 May 2017 17:02:09 +0200
+Subject: [PATCH 130/303] @B do not optimize with indirect jumps and unknown
+ labels. @R doo not indicate regs for static_chain/struct_value if not used
+
+---
+ gcc/DATESTAMP | 2 +-
+ gcc/bbb-opts.c | 151 ++++++++++++++++++++++++++--------------------
+ gcc/config/m68k/amigaos.c | 68 ++++++++++++---------
+ gcc/config/m68k/amigaos.h | 11 ++++
+ 4 files changed, 138 insertions(+), 94 deletions(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index f9bb1bba46d4..3f03e820cb0b 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170517
++20170520
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index dd2923873c1d..848c18e3be52 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -424,7 +424,7 @@ class insn_info
+ src_mem = false;
+ dst_plus = false;
+ src_plus = false;
+- src_op = (rtx_code)0;
++ src_op = (rtx_code) 0;
+ src_ee = false;
+ src_const = false;
+
+@@ -888,7 +888,7 @@ insn_info::fledder (rtx set)
+ else if (GET_CODE(src) == CONST_INT)
+ {
+ src_const = true;
+- src_mem_addr = INTVAL(src);
++ src_intval = INTVAL(src);
+ }
+ if (alt_src_reg)
+ src_reg = alt_src_reg;
+@@ -1002,7 +1002,7 @@ void
+ insn_info::plus_to_move (rtx_insn * newinsn)
+ {
+ insn = newinsn;
+- src_op = (rtx_code)0;
++ src_op = (rtx_code) 0;
+ src_reg = XEXP(PATTERN (newinsn), 1);
+ insn2index.insert (std::make_pair (insn, this));
+ // usage flags did not change
+@@ -1358,14 +1358,19 @@ update_insn_infos (void)
+ usable_regs &= ~(1 << STACK_POINTER_REGNUM);
+ }
+
++enum AbortCodes
++{
++ E_OK, E_NO_JUMP_LABEL, E_JUMP_TABLE_MISMATCH, E_JUMP_GOTO_LABEL
++};
++
+ /*
+ * Create a filtered view of insns - keep only those to work with.
+ */
+-static int
++static unsigned
+ update_insns ()
+ {
+ rtx_insn *insn, *next;
+-
++ unsigned result = 0;
+ rtx jump_table = 0;
+
+ clear ();
+@@ -1386,54 +1391,69 @@ update_insns ()
+ {
+ inproepilogue = 0;
+
+- ii.mark_jump ();
++ if (ANY_RETURN_P(PATTERN (insn)))
++ continue;
+
+- rtx pattern = PATTERN (insn);
+- if (GET_CODE(pattern) == PARALLEL)
++ ii.mark_jump ();
++ if (jump_table)
+ {
+- /*
+- * Use the jump_table_data and add all to the lookup
+- */
+- if (jump_table == 0)
++ if (XEXP(jump_table, 0) != insn)
+ {
+- // still allow if_then_else inside a parallel insn
+- rtx ite = XVECEXP(pattern, 0, 0);
+- if (XEXP(ite, 0) != pc_rtx || GET_CODE(XEXP(ite, 1)) != IF_THEN_ELSE)
++ if (be_very_verbose)
+ {
+ debug_rtx (insn);
+- return 1; // do not optimize.
++ debug_rtx (jump_table);
+ }
+- rtx_insn * label = (rtx_insn *) JUMP_LABEL(insn);
+- label2jump.insert (std::make_pair (label->u2.insn_uid, insn));
++ result = E_JUMP_TABLE_MISMATCH;
++ jump_table = 0;
++ continue;
+ }
+- else if (XEXP(jump_table, 0) != insn)
++
++ // -> jump_table_data
++ rtx table = PATTERN (XEXP(jump_table, 1));
++ if (GET_CODE(table) == ADDR_DIFF_VEC || GET_CODE(table) == ADDR_VEC)
+ {
+- debug_rtx (insn);
+- return 2;
++ int k = GET_CODE(table) == ADDR_DIFF_VEC;
++ for (int j = 0; j < XVECLEN(table, k); ++j)
++ {
++ rtx ref = XVECEXP(table, k, j);
++ if (!LABEL_REF_NONLOCAL_P(ref))
++ {
++ rtx label = XEXP(ref, 0);
++ label2jump.insert (std::make_pair (label->u2.insn_uid, insn));
++ }
++ }
+ }
+ else
+ {
+- // -> jump_table_data
+- rtx table = PATTERN (XEXP(jump_table, 1));
+- for (int j = 0; j < XVECLEN(table, 1); ++j)
++ if (be_very_verbose)
+ {
+- rtx ref = XVECEXP(table, 1, j);
+- rtx label = XEXP(ref, 0);
+- label2jump.insert (std::make_pair (label->u2.insn_uid, insn));
++ debug_rtx (insn);
++ debug_rtx (jump_table);
+ }
++ result = E_JUMP_GOTO_LABEL;
++ jump_table = 0;
++ continue;
+ }
+ jump_table = 0;
+ }
+ else
+ {
+ rtx_insn * label = (rtx_insn *) JUMP_LABEL(insn);
++ if (!label)
++ {
++ if (be_very_verbose)
++ debug_rtx (insn);
++ result = E_NO_JUMP_LABEL;
++ continue;
++ }
+ label2jump.insert (std::make_pair (label->u2.insn_uid, insn));
+ }
+-
+ }
+ else if (LABEL_P(insn))
+ {
+ ii.mark_label ();
++ jump_table = 0;
+ }
+ else if (CALL_P(insn))
+ {
+@@ -1468,7 +1488,7 @@ update_insns ()
+ update_insn2index ();
+ update_insn_infos ();
+
+- return 0;
++ return result;
+ }
+
+ /* convert the lowest set bit into a register number. */
+@@ -2953,7 +2973,7 @@ opt_absolute (void)
+ {
+ insn_info & jj = infos[j];
+ /* TODO: continue also at jump target */
+- if (jj.is_jump())
++ if (jj.is_jump ())
+ continue;
+ /* TODO: check if label is visited only from jump targets from herein. then the label is ok. */
+ if (jj.is_label ())
+@@ -3159,60 +3179,59 @@ namespace
+ if (be_very_verbose)
+ log ("ENTER\n");
+
+- for (;;)
++ unsigned r = update_insns ();
++ if (!r)
+ {
+- int done = 1;
+- int r = update_insns ();
+- if (r)
++ for (;;)
+ {
+- if (be_verbose)
+- log ("no bbb optimization code %d\n", r);
+- return 0;
+- }
+- if (do_opt_strcpy && opt_strcpy ())
+- done = 0, update_insns ();
++ int done = 1;
++ if (do_opt_strcpy && opt_strcpy ())
++ done = 0, update_insns ();
+
+- if (do_commute_add_move && opt_commute_add_move ())
+- done = 0, update_insns ();
++ if (do_commute_add_move && opt_commute_add_move ())
++ done = 0, update_insns ();
+
+- if (do_propagate_moves && opt_propagate_moves ())
+- done = 0, update_insns ();
++ if (do_propagate_moves && opt_propagate_moves ())
++ done = 0, update_insns ();
+
+- if (do_const_cmp_to_sub && opt_const_cmp_to_sub ())
+- done = 0, update_insns ();
++ if (do_const_cmp_to_sub && opt_const_cmp_to_sub ())
++ done = 0, update_insns ();
+
+- if (do_merge_add && opt_merge_add ())
+- done = 0;
++ if (do_merge_add && opt_merge_add ())
++ done = 0;
+
+- if (do_elim_dead_assign && opt_elim_dead_assign ())
+- done = 0, update_insns ();
++ if (do_elim_dead_assign && opt_elim_dead_assign ())
++ done = 0, update_insns ();
+
+- if (do_absolute && opt_absolute ())
+- done = 0;
++ if (do_absolute && opt_absolute ())
++ done = 0;
+
+- if (do_bb_reg_rename)
+- {
+- while (opt_reg_rename ())
++ if (do_bb_reg_rename)
+ {
+- update_insns ();
+- done = 0;
++ while (opt_reg_rename ())
++ {
++ update_insns ();
++ done = 0;
++ }
+ }
+- }
+
+- if (done)
+- break;
+- }
++ if (done)
++ break;
++ }
+
+- if (do_shrink_stack_frame)
+- {
+- if (opt_shrink_stack_frame ())
+- update_insns ();
++ if (do_shrink_stack_frame)
++ {
++ if (opt_shrink_stack_frame ())
++ update_insns ();
++ }
+ }
++ if (r && be_verbose)
++ log ("no bbb optimization code %d\n", r);
+
+ if (strchr (string_bbb_opts, 'X') || strchr (string_bbb_opts, 'x'))
+ dump_insns ("bbb", strchr (string_bbb_opts, 'X'));
+
+- return 0;
++ return r;
+ }
+
+ } // anon namespace
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index 9166b91a69eb..a79b5cddd91b 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -39,6 +39,7 @@
+ #include "target.h"
+ #include "diagnostic-core.h"
+ #include "langhooks.h"
++#include "function.h"
+ #include "config/m68k/amigaos.h"
+
+ //#define MYDEBUG 1
+@@ -50,7 +51,6 @@
+
+ //int amiga_declare_object;
+
+-
+ #if 0
+ static int amigaos_put_in_text (tree);
+ static rtx gen_stack_management_call (rtx, rtx, const char *);
+@@ -436,24 +436,18 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl)
+ if (!next_param && TREE_VALUE (param) != void_type_node)
+ cum->num_of_regs = 0;
+ }
+-
+- /* check for return values passed in a0 */
+- if (cum->num_of_regs)
+- {
+- tree type = TYPE_SIZE(TREE_TYPE (DECL_RESULT (current_function_decl)));
+- int sz = type ? TREE_INT_CST_LOW(type) : 0;
+- if (sz > 64) /* mark a0 as already used. */
+- cum->regs_already_used |= 1 << 8;
+- }
+ }
+
+- //#if ! defined (PCC_STATIC_STRUCT_RETURN) && defined (M68K_STRUCT_VALUE_REGNUM)
+- // /* If return value is a structure, and we pass the buffer address in a
+- // register, we can't use this register for our own purposes.
+- // FIXME: Something similar would be useful for static chain. */
+- // if (fntype && aggregate_value_p (TREE_TYPE (fntype), fntype))
+- // cum->regs_already_used |= (1 << M68K_STRUCT_VALUE_REGNUM);
+- //#endif
++#if ! defined (PCC_STATIC_STRUCT_RETURN) && defined (M68K_STRUCT_VALUE_REGNUM)
++ /* If return value is a structure, and we pass the buffer address in a
++ register, we can't use this register for our own purposes.
++ FIXME: Something similar would be useful for static chain. */
++ if (fntype && aggregate_value_p (TREE_TYPE(fntype), fntype))
++ cum->regs_already_used |= (1 << M68K_STRUCT_VALUE_REGNUM);
++#endif
++
++ if (fntype && DECL_STATIC_CHAIN(fntype))
++ cum->regs_already_used |= (1 << STATIC_CHAIN_REGNUM);
+
+ if (fntype)
+ cum->formal_type = TYPE_ARG_TYPES(fntype);
+@@ -463,9 +457,8 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl)
+ DPRINTF(("1amigaos_init_cumulative_args %p -> %d\r\n", cum, cum->num_of_regs));
+ }
+
+-
+ int
+-amigaos_function_arg_reg(unsigned regno)
++amigaos_function_arg_reg (unsigned regno)
+ {
+ return (mycum.regs_already_used & (1 << regno)) != 0;
+ }
+@@ -802,20 +795,22 @@ amiga_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_U
+ #else
+ extern void
+ amiga_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_UNUSED)
+-{
+- if (0 == strncmp(".text", name, 5))
++ {
++ if (0 == strncmp(".text", name, 5))
+ name = ".text";
+
+- if (0 == strncmp("section ", name, 8)) {
++ if (0 == strncmp("section ", name, 8))
++ {
+ // fprintf (asm_out_file, "\t.section\t%s\n", name);
+- fprintf (asm_out_file, "\t%s\n", name);
+- } else {
+- fprintf (asm_out_file, "\tsection %s\n", name);
++ fprintf (asm_out_file, "\t%s\n", name);
++ }
++ else
++ {
++ fprintf (asm_out_file, "\tsection %s\n", name);
++ }
+ }
+-}
+ #endif
+
+-
+ /* Baserel support. */
+
+ /**
+@@ -846,3 +841,22 @@ read_only_operand (rtx operand)
+ return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P(operand);
+ return 1;
+ }
++
++rtx
++amigaos_struct_value_rtx (tree fntype, int incoming ATTRIBUTE_UNUSED)
++{
++ if (fntype && aggregate_value_p (TREE_TYPE(fntype), fntype))
++ return gen_rtx_REG (Pmode, M68K_STRUCT_VALUE_REGNUM);
++
++ return 0;
++}
++
++rtx
++amigaos_static_chain_rtx (const_tree fntype, bool incoming ATTRIBUTE_UNUSED)
++{
++ if (fntype && DECL_STATIC_CHAIN(fntype))
++ return gen_rtx_REG (Pmode, M68K_STRUCT_VALUE_REGNUM);
++
++ return 0;
++}
++
+diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h
+index 284328683c37..c564c3f2db67 100644
+--- gcc/config/m68k/amigaos.h
++++ gcc/config/m68k/amigaos.h
+@@ -466,3 +466,14 @@ amigaos_rtx_costs (rtx, machine_mode, int, int, int *, bool);
+ && GET_CODE(XEXP(XEXP(XEXP(x, 0), 1), 0)) == UNSPEC \
+ )
+
++#undef TARGET_STRUCT_VALUE_RTX
++#define TARGET_STRUCT_VALUE_RTX amigaos_struct_value_rtx
++rtx
++amigaos_struct_value_rtx(tree fntype,
++ int incoming ATTRIBUTE_UNUSED);
++
++#undef TARGET_STATIC_CHAIN
++#define TARGET_STATIC_CHAIN amigaos_static_chain_rtx
++rtx
++amigaos_static_chain_rtx(const_tree fntype,
++ bool incoming ATTRIBUTE_UNUSED);
+
+From bade0e4a363da3d63371623f36c746e976e22a18 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 21 May 2017 07:23:52 +0200
+Subject: [PATCH 131/303] @B fix return reg to comply test cases
+
+---
+ gcc/DATESTAMP | 2 +-
+ gcc/config/m68k/m68kamigaos.h | 5 ++++-
+ 2 files changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 3f03e820cb0b..301f35608896 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170520
++20170521
+diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h
+index f636e397cfca..a81007bb15d5 100644
+--- gcc/config/m68k/m68kamigaos.h
++++ gcc/config/m68k/m68kamigaos.h
+@@ -264,7 +264,10 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ /* put return values in FPU build in FP0 Reg */
+ #undef FUNCTION_VALUE_REGNO_P
+ #define FUNCTION_VALUE_REGNO_P(N) \
+- ((N) == D0_REG || (N) == A0_REG || (TARGET_68881 && (N) == FP0_REG))
++ ((N) == D0_REG || (TARGET_68881 && (N) == FP0_REG))
++
++// see 930623-1.c
++// ((N) == D0_REG || (N) == A0_REG || (TARGET_68881 && (N) == FP0_REG))
+
+ /* Inform the program which CPU we compile for. */
+
+
+From 3401ac796cd87583972c39b6ab730bf5faead050 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 22 May 2017 20:41:51 +0200
+Subject: [PATCH 132/303] @R use a dynamic static_chain register to avoid
+ clashes with asm parameters
+
+---
+ gcc/config/m68k/amigaos.c | 33 +++++++++++++++++++++++++++++----
+ 1 file changed, 29 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index a79b5cddd91b..8a92ef99db27 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -447,7 +447,11 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl)
+ #endif
+
+ if (fntype && DECL_STATIC_CHAIN(fntype))
+- cum->regs_already_used |= (1 << STATIC_CHAIN_REGNUM);
++ {
++ rtx reg = amigaos_static_chain_rtx (decl, 0);
++ if (reg)
++ cum->regs_already_used |= (1 << REGNO(reg));
++ }
+
+ if (fntype)
+ cum->formal_type = TYPE_ARG_TYPES(fntype);
+@@ -852,10 +856,31 @@ amigaos_struct_value_rtx (tree fntype, int incoming ATTRIBUTE_UNUSED)
+ }
+
+ rtx
+-amigaos_static_chain_rtx (const_tree fntype, bool incoming ATTRIBUTE_UNUSED)
++amigaos_static_chain_rtx (const_tree decl, bool incoming ATTRIBUTE_UNUSED)
+ {
+- if (fntype && DECL_STATIC_CHAIN(fntype))
+- return gen_rtx_REG (Pmode, M68K_STRUCT_VALUE_REGNUM);
++ if (!decl || !DECL_STATIC_CHAIN(decl))
++ return 0;
++
++ tree fntype = TREE_TYPE(decl);
++
++ unsigned used = 0;
++
++ for (tree formal_type = TYPE_ARG_TYPES(fntype); formal_type; formal_type = TREE_CHAIN(formal_type))
++ {
++ tree asmtree = TYPE_ATTRIBUTES(formal_type);
++ if (!asmtree || strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(asmtree))))
++ continue;
++
++ unsigned regno = TREE_FIXED_CST_PTR(TREE_VALUE(asmtree))->data.low;
++ used |= 1 << regno;
++ }
++
++ if (!(used & (1 << 9)))
++ return gen_rtx_REG (Pmode, 9);
++ if (!(used & (1 << 10)))
++ return gen_rtx_REG (Pmode, 10);
++ if (!(used & (1 << 11)))
++ return gen_rtx_REG (Pmode, 11);
+
+ return 0;
+ }
+
+From 74d34b98a82894145e0021ed0fc00592210413d7 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 23 May 2017 22:22:26 +0200
+Subject: [PATCH 133/303] @B fix function flow scanning
+
+---
+ gcc/bbb-opts.c | 95 +++++++++++++++++++++++++++-------------------------------
+ 1 file changed, 44 insertions(+), 51 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 848c18e3be52..a06f1577fb94 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -155,12 +155,15 @@ class insn_info
+ int src_intval;
+ unsigned src_mem_addr;
+
++ bool visited;
++
+ public:
+ insn_info (rtx_insn * i = 0, int p = 0) :
+ insn (i), myuse (0), hard (0), use (0), def (0), proepi (p), stack (false), label (false), jump (false), call (
+ false), compare (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus (false), src_op (
+ (rtx_code) 0), src_ee (false), src_const (false), mode (VOIDmode), dst_reg (0), dst_mem_reg (0), dst_symbol (
+- 0), src_reg (0), src_mem_reg (0), src_symbol (0), dst_mem_addr (0), src_intval (0), src_mem_addr (0)
++ 0), src_reg (0), src_mem_reg (0), src_symbol (0), dst_mem_addr (0), src_intval (0), src_mem_addr (0), visited (
++ false)
+ {
+ }
+
+@@ -408,14 +411,6 @@ class insn_info
+ return proepi;
+ }
+
+- inline void
+- reset ()
+- {
+- use = 0;
+- def = 0;
+- hard = 0;
+- }
+-
+ inline void
+ reset_flags ()
+ {
+@@ -574,34 +569,6 @@ class insn_info
+ return *this;
+ }
+
+-#if 0
+- inline insn_info
+- operator | (insn_info const & o) const
+- {
+- insn_info t;
+- t.use = use | o.use;
+- t.def = def | o.def;
+- t.hard = hard | o.hard;
+- return t;
+- }
+-
+- inline bool
+- operator == (insn_info const & o)
+- {
+- return use == o.use;
+- }
+-
+- inline insn_info
+- operator ~ () const
+- {
+- insn_info t;
+- t.use = ~use;
+- t.def = ~def;
+- t.hard = ~hard;
+- return t;
+- }
+-#endif
+-
+ inline insn_info &
+ make_hard ()
+ {
+@@ -628,6 +595,18 @@ class insn_info
+ return true;
+ }
+
++ inline bool
++ visit () const
++ {
++ return visited;
++ }
++
++ inline void
++ mark_visited ()
++ {
++ visited = true;
++ }
++
+ void
+ scan ();
+
+@@ -959,6 +938,9 @@ typedef std::multimap<int, rtx_insn *>::iterator l2j_iterator;
+ static std::map<rtx_insn *, insn_info *> insn2index;
+ typedef std::map<rtx_insn *, insn_info *>::iterator i2i_iterator;
+
++static std::set<unsigned> returns;
++typedef std::set<unsigned>::iterator su_iterator;
++
+ static insn_info * info0;
+ static unsigned usable_regs;
+
+@@ -1148,6 +1130,7 @@ clear (void)
+ label2jump.clear ();
+ insn2index.clear ();
+ infos.clear ();
++ returns.clear ();
+ }
+
+ /*
+@@ -1256,11 +1239,14 @@ dump_insns (char const * name, bool all)
+ static void
+ update_insn_infos (void)
+ {
+- /* own analyze reg life */
++ /* add all return (jump outs) and start analysis there. */
+ std::vector<std::pair<unsigned, insn_info> > todo;
+- todo.push_back (std::make_pair (infos.size () - 1, insn_info ()));
++ for (su_iterator i = returns.begin (); i != returns.end (); ++i)
++ todo.push_back (std::make_pair (*i, insn_info ()));
++
++ if (todo.begin () == todo.end ())
++ todo.push_back (std::make_pair (infos.size () - 1, insn_info ()));
+
+- int pass = 0;
+ while (!todo.empty ())
+ {
+ std::pair<unsigned, insn_info> p = *todo.rbegin ();
+@@ -1270,17 +1256,18 @@ update_insn_infos (void)
+
+ for (int pos = p.first; pos >= 0; --pos)
+ {
+- rtx_insn * insn = infos[pos].get_insn ();
++ insn_info & pp = infos[pos];
++ rtx_insn * insn = pp.get_insn ();
+ /* can be NULL as used in opt_shrink_stack_frame(). */
+ if (!insn)
+ continue;
+
+ /* no new information -> break. */
+- if (pass && infos[pos].contains (ii))
++ if (pp.in_proepi () == 0 && pp.visit () && pp.contains (ii))
+ break;
+
+ ii.clear_hard_def ();
+- ii.merge (infos[pos]);
++ ii.merge (pp);
+
+ if (LABEL_P(insn))
+ {
+@@ -1295,6 +1282,8 @@ update_insn_infos (void)
+ continue;
+ }
+
++ pp.mark_visited ();
++
+ rtx pattern = PATTERN (insn);
+ insn_info use (insn);
+ use.scan ();
+@@ -1304,9 +1293,11 @@ update_insn_infos (void)
+ }
+ else if (JUMP_P(insn))
+ {
+- if (ANY_RETURN_P(pattern))
++ if (pos != p.first)
+ {
+- ii.reset ();
++ su_iterator k = returns.find (pos);
++ if (k != returns.end ())
++ break;
+ }
+ }
+ else if (GET_CODE (pattern) == USE || GET_CODE (pattern) == CLOBBER)
+@@ -1330,10 +1321,9 @@ update_insn_infos (void)
+ use.make_hard ();
+
+ ii.merge (use);
+- infos[pos].update (ii);
++ pp.update (ii);
+ ii.updateWith (use);
+ }
+- ++pass;
+ }
+
+ /* fill the mask of general used regs. */
+@@ -1389,10 +1379,13 @@ update_insns ()
+
+ if (JUMP_P(insn))
+ {
+- inproepilogue = 0;
+-
+- if (ANY_RETURN_P(PATTERN (insn)))
+- continue;
++ if (inproepilogue || ANY_RETURN_P(PATTERN (insn)))
++ {
++ returns.insert (infos.size () - 1);
++ inproepilogue = 0;
++ if (ANY_RETURN_P(PATTERN (insn)))
++ continue;
++ }
+
+ ii.mark_jump ();
+ if (jump_table)
+
+From b1334e77f8e493eaeb362392f035711d06484be7 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 23 May 2017 22:22:44 +0200
+Subject: [PATCH 134/303] @B fix static_chain register handling
+
+---
+ gcc/config/m68k/amigaos.c | 24 ++++++++++++------------
+ 1 file changed, 12 insertions(+), 12 deletions(-)
+
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index 8a92ef99db27..dc2f2ac74369 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -602,7 +602,6 @@ amigaos_function_arg (cumulative_args_t cum_v, machine_mode mode, const_tree typ
+ void
+ amiga_emit_regparm_clobbers (void)
+ {
+- rtx sp = gen_raw_REG (Pmode, 15);
+ for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+ if (mycum.regs_already_used & (1 << i))
+ {
+@@ -861,19 +860,18 @@ amigaos_static_chain_rtx (const_tree decl, bool incoming ATTRIBUTE_UNUSED)
+ if (!decl || !DECL_STATIC_CHAIN(decl))
+ return 0;
+
+- tree fntype = TREE_TYPE(decl);
+-
+ unsigned used = 0;
++ tree fntype = TREE_TYPE(decl);
++ if (fntype)
++ for (tree formal_type = TYPE_ARG_TYPES(fntype); formal_type; formal_type = TREE_CHAIN(formal_type))
++ {
++ tree asmtree = TYPE_ATTRIBUTES(TREE_VALUE(formal_type));
++ if (!asmtree || strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(asmtree))))
++ continue;
+
+- for (tree formal_type = TYPE_ARG_TYPES(fntype); formal_type; formal_type = TREE_CHAIN(formal_type))
+- {
+- tree asmtree = TYPE_ATTRIBUTES(formal_type);
+- if (!asmtree || strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(asmtree))))
+- continue;
+-
+- unsigned regno = TREE_FIXED_CST_PTR(TREE_VALUE(asmtree))->data.low;
+- used |= 1 << regno;
+- }
++ unsigned regno = TREE_FIXED_CST_PTR(TREE_VALUE(asmtree))->data.low;
++ used |= 1 << regno;
++ }
+
+ if (!(used & (1 << 9)))
+ return gen_rtx_REG (Pmode, 9);
+@@ -881,6 +879,8 @@ amigaos_static_chain_rtx (const_tree decl, bool incoming ATTRIBUTE_UNUSED)
+ return gen_rtx_REG (Pmode, 10);
+ if (!(used & (1 << 11)))
+ return gen_rtx_REG (Pmode, 11);
++ if (!(used & (1 << 14)))
++ return gen_rtx_REG (Pmode, 14);
+
+ return 0;
+ }
+
+From 5b9f0616bb8d5bf7cca7daaa9b5cd4056e0e6f9e Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 24 May 2017 16:27:49 +0200
+Subject: [PATCH 135/303] @B fix stack frame shrinking
+
+---
+ gcc/bbb-opts.c | 234 ++++++++++++++++++++++++++++++++++++++++++++++++++-------
+ 1 file changed, 208 insertions(+), 26 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index a06f1577fb94..43bcf138fc20 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -157,13 +157,18 @@ class insn_info
+
+ bool visited;
+
++ int sp_offset;
++
++ int dst_autoinc;
++ int src_autoinc;
++
+ public:
+ insn_info (rtx_insn * i = 0, int p = 0) :
+ insn (i), myuse (0), hard (0), use (0), def (0), proepi (p), stack (false), label (false), jump (false), call (
+ false), compare (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus (false), src_op (
+ (rtx_code) 0), src_ee (false), src_const (false), mode (VOIDmode), dst_reg (0), dst_mem_reg (0), dst_symbol (
+ 0), src_reg (0), src_mem_reg (0), src_symbol (0), dst_mem_addr (0), src_intval (0), src_mem_addr (0), visited (
+- false)
++ false), sp_offset (0), dst_autoinc (0), src_autoinc (0)
+ {
+ }
+
+@@ -414,6 +419,8 @@ class insn_info
+ inline void
+ reset_flags ()
+ {
++ label = false;
++ jump = false;
+ compare = false;
+ dst_mem = false;
+ src_mem = false;
+@@ -435,6 +442,21 @@ class insn_info
+
+ src_intval = 0;
+ src_mem_addr = 0;
++
++ dst_autoinc = 0;
++ src_autoinc = 0;
++ }
++
++ inline int
++ get_src_autoinc () const
++ {
++ return src_autoinc;
++ }
++
++ inline int
++ get_dst_autoinc () const
++ {
++ return dst_autoinc;
+ }
+
+ inline bool
+@@ -595,8 +617,20 @@ class insn_info
+ return true;
+ }
+
++ inline int
++ get_sp_offset () const
++ {
++ return sp_offset;
++ }
++
++ inline void
++ set_sp_offset (int sp)
++ {
++ sp_offset = sp;
++ }
++
+ inline bool
+- visit () const
++ is_visited () const
+ {
+ return visited;
+ }
+@@ -607,6 +641,12 @@ class insn_info
+ visited = true;
+ }
+
++ inline void
++ clear_visited ()
++ {
++ visited = false;
++ }
++
+ void
+ scan ();
+
+@@ -770,6 +810,12 @@ insn_info::fledder (rtx set)
+ {
+ dst_mem = true;
+ rtx mem = XEXP(dst, 0);
++
++ if (GET_CODE(mem) == POST_INC)
++ dst_autoinc = 1, mem = XEXP(mem, 0);
++ else if (GET_CODE(mem) == PRE_DEC)
++ dst_autoinc = -1, mem = XEXP(mem, 0);
++
+ if (REG_P(mem))
+ dst_mem_reg = mem;
+ else if (GET_CODE(mem) == CONST_INT)
+@@ -831,6 +877,12 @@ insn_info::fledder (rtx set)
+ {
+ src_mem = true;
+ rtx mem = XEXP(src, 0);
++
++ if (GET_CODE(mem) == POST_INC)
++ src_autoinc = 1, mem = XEXP(mem, 0);
++ else if (GET_CODE(mem) == PRE_DEC)
++ src_autoinc = -1, mem = XEXP(mem, 0);
++
+ if (REG_P(mem))
+ src_mem_reg = mem;
+ else if (GET_CODE(mem) == CONST_INT)
+@@ -932,10 +984,15 @@ temp_reg_rename (std::vector<std::pair<rtx *, rtx> > & loc, rtx x, unsigned oldr
+ static std::vector<insn_info> infos;
+ typedef std::vector<insn_info>::iterator insn_info_iterator;
+
++// insn->u2.insn_uid -> rtx_insn *
+ static std::multimap<int, rtx_insn *> label2jump;
+ typedef std::multimap<int, rtx_insn *>::iterator l2j_iterator;
+
+-static std::map<rtx_insn *, insn_info *> insn2index;
++// index -> index
++static std::multimap<unsigned, unsigned> jump2label;
++typedef std::multimap<unsigned, unsigned>::iterator j2l_iterator;
++
++static std::map<rtx_insn *, insn_info *> insn2info;
+ typedef std::map<rtx_insn *, insn_info *>::iterator i2i_iterator;
+
+ static std::set<unsigned> returns;
+@@ -948,16 +1005,31 @@ static void
+ update_insn2index ()
+ {
+ infos.reserve (infos.size () * 8 / 7 + 2);
+- insn2index.clear ();
++ insn2info.clear ();
+ /* needs a separate pass since the insn_infos require fixed addresses for ->get_index() */
+ for (unsigned i = 0; i < infos.size (); ++i)
+ {
+ insn_info & ii = infos[i];
+- insn2index.insert (std::make_pair (ii.get_insn (), &ii));
++ insn2info.insert (std::make_pair (ii.get_insn (), &ii));
+ }
+ info0 = &infos[0];
+ }
+
++static void
++update_label2jump ()
++{
++ for (unsigned index = 0; index < infos.size (); ++index)
++ {
++ insn_info & ii = infos[index];
++ insn2info.insert (std::make_pair (ii.get_insn (), &ii));
++
++ if (ii.is_label ())
++ for (l2j_iterator i = label2jump.find (ii.get_insn ()->u2.insn_uid), k = i;
++ i != label2jump.end () && i->first == k->first; ++i)
++ jump2label.insert (std::make_pair (insn2info.find (i->second)->second->get_index (), index));
++ }
++}
++
+ int
+ insn_info::get_index () const
+ {
+@@ -986,7 +1058,7 @@ insn_info::plus_to_move (rtx_insn * newinsn)
+ insn = newinsn;
+ src_op = (rtx_code) 0;
+ src_reg = XEXP(PATTERN (newinsn), 1);
+- insn2index.insert (std::make_pair (insn, this));
++ insn2info.insert (std::make_pair (insn, this));
+ // usage flags did not change
+ }
+
+@@ -997,8 +1069,8 @@ insn_info::swap_adds (rtx_insn * newinsn, insn_info & ii)
+
+ std::swap (*this, ii);
+
+- insn2index.insert (std::make_pair (insn, this));
+- insn2index.insert (std::make_pair (ii.insn, &ii));
++ insn2info.insert (std::make_pair (insn, this));
++ insn2info.insert (std::make_pair (ii.insn, &ii));
+
+ // usage flags did not change
+ }
+@@ -1065,7 +1137,6 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol)
+ unsigned offset = addr - base;
+ if (offset <= 0x7ffe)
+ {
+- rtx olddst = dst;
+ if (base == addr)
+ dst = gen_rtx_MEM (mode, reg);
+ else
+@@ -1119,7 +1190,7 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol)
+
+ mark_use (regno);
+
+- insn2index.insert (std::make_pair (insn, this));
++ insn2info.insert (std::make_pair (insn, this));
+ }
+ /*
+ * Reset collected data.
+@@ -1128,7 +1199,8 @@ static void
+ clear (void)
+ {
+ label2jump.clear ();
+- insn2index.clear ();
++ jump2label.clear ();
++ insn2info.clear ();
+ infos.clear ();
+ returns.clear ();
+ }
+@@ -1160,8 +1232,8 @@ void
+ append_reg_usage (FILE * f, rtx_insn * insn)
+ {
+
+- i2i_iterator i = insn2index.find (insn);
+- if (i == insn2index.end ())
++ i2i_iterator i = insn2info.find (insn);
++ if (i == insn2info.end ())
+ return;
+
+ insn_info & ii = *i->second;
+@@ -1263,7 +1335,7 @@ update_insn_infos (void)
+ continue;
+
+ /* no new information -> break. */
+- if (pp.in_proepi () == 0 && pp.visit () && pp.contains (ii))
++ if (pp.in_proepi () == 0 && pp.is_visited () && pp.contains (ii))
+ break;
+
+ ii.clear_hard_def ();
+@@ -1275,8 +1347,8 @@ update_insn_infos (void)
+ for (l2j_iterator i = label2jump.find (insn->u2.insn_uid), k = i;
+ i != label2jump.end () && i->first == k->first; ++i)
+ {
+- i2i_iterator j = insn2index.find (i->second);
+- if (j != insn2index.end ())
++ i2i_iterator j = insn2info.find (i->second);
++ if (j != insn2info.end ())
+ todo.push_back (std::make_pair (j->second->get_index (), ii));
+ }
+ continue;
+@@ -1293,11 +1365,14 @@ update_insn_infos (void)
+ }
+ else if (JUMP_P(insn))
+ {
+- if (pos != p.first)
++ if ((unsigned) pos != p.first)
+ {
+ su_iterator k = returns.find (pos);
+ if (k != returns.end ())
+- break;
++ {
++ pp.clear_visited ();
++ break;
++ }
+ }
+ }
+ else if (GET_CODE (pattern) == USE || GET_CODE (pattern) == CLOBBER)
+@@ -1350,7 +1425,7 @@ update_insn_infos (void)
+
+ enum AbortCodes
+ {
+- E_OK, E_NO_JUMP_LABEL, E_JUMP_TABLE_MISMATCH, E_JUMP_GOTO_LABEL
++ E_OK, E_NO_JUMP_LABEL, E_JUMP_TABLE_MISMATCH, E_JUMP_GOTO_LABEL, E_SP_MISMATCH
+ };
+
+ /*
+@@ -1598,8 +1673,8 @@ opt_reg_rename (void)
+ for (l2j_iterator i = label2jump.find (insn->u2.insn_uid), k = i;
+ i != label2jump.end () && i->first == k->first; ++i)
+ {
+- i2i_iterator j = insn2index.find (i->second);
+- if (j == insn2index.end ())
++ i2i_iterator j = insn2info.find (i->second);
++ if (j == insn2info.end ())
+ continue;
+
+ unsigned start = j->second->get_index ();
+@@ -1647,8 +1722,8 @@ opt_reg_rename (void)
+ /* follow jump and/or next insn. */
+ if (JUMP_P(insn))
+ {
+- i2i_iterator j = insn2index.find ((rtx_insn *) JUMP_LABEL(insn));
+- if (j == insn2index.end ())
++ i2i_iterator j = insn2info.find ((rtx_insn *) JUMP_LABEL(insn));
++ if (j == insn2info.end ())
+ {
+ /* whoops - label not found. */
+ mask = 0;
+@@ -2488,6 +2563,86 @@ opt_merge_add (void)
+ return change_count;
+ }
+
++/* Update the insn_infos to 'know' the sp offset. */
++static unsigned
++track_sp ()
++{
++ // reset visited flags
++ for (unsigned index = 0; index < infos.size (); ++index)
++ {
++ insn_info & ii = infos[index];
++ ii.clear_visited ();
++ ii.set_sp_offset (0);
++ }
++
++ // add entry point
++ std::vector<unsigned> todo;
++ todo.push_back (0);
++
++ while (todo.size () > 0)
++ {
++ unsigned startpos = todo[todo.size () - 1];
++ todo.pop_back ();
++
++ int sp_offset = infos[startpos].get_sp_offset ();
++
++ for (unsigned index = startpos; index < infos.size (); ++index)
++ {
++ insn_info & ii = infos[index];
++ if (ii.in_proepi ())
++ continue;
++
++ // already visited? sp_offset must match
++ if (ii.is_visited ())
++ {
++ if (ii.get_sp_offset () != sp_offset)
++ return E_SP_MISMATCH;
++ break;
++ }
++
++ // mark current insn_info and set sp_offset
++ ii.mark_visited ();
++ ii.set_sp_offset (sp_offset);
++
++ // add all referred labels
++ if (ii.is_jump ())
++ {
++ for (j2l_iterator i = jump2label.find (index), k = i; i != jump2label.end () && i->first == k->first; ++i)
++ {
++ insn_info & ll = infos[i->second];
++ if (ll.is_visited () && ll.get_sp_offset () != sp_offset)
++ return E_SP_MISMATCH;
++
++ ll.set_sp_offset (sp_offset);
++ todo.push_back (i->second);
++ }
++ continue;
++ }
++
++ // is sp modified directly
++ if (ii.is_dst_reg () && ii.get_dst_regno () == STACK_POINTER_REGNUM)
++ {
++ // handle sp = sp + const_int
++ if (!ii.is_src_reg () || ii.get_src_regno () != STACK_POINTER_REGNUM || ii.get_src_op () != PLUS)
++ return E_SP_MISMATCH;
++
++ sp_offset = sp_offset + ii.get_src_intval ();
++ continue;
++ }
++
++ // handle dst mem autoinc
++ if (ii.is_dst_mem () && ii.get_dst_mem_regno () == STACK_POINTER_REGNUM && ii.get_dst_autoinc ())
++ sp_offset += GET_MODE_SIZE(ii.get_mode()) * ii.get_dst_autoinc ();
++
++ // handle src mem autoinc
++ if (ii.is_src_mem () && ii.get_src_mem_regno () == STACK_POINTER_REGNUM && ii.get_src_autoinc ())
++ sp_offset += GET_MODE_SIZE(ii.get_mode()) * ii.get_src_autoinc ();
++ }
++ }
++
++ return 0;
++}
++
+ /**
+ * 1. scan for all used registers.
+ * 2. scan the stack from for omittable push/pop
+@@ -2517,6 +2672,11 @@ opt_shrink_stack_frame (void)
+ if (!infos.size ())
+ return 0;
+
++ /* needed to track sp correctly. */
++ update_label2jump ();
++ if (track_sp ())
++ return 0; // do nothing on stack errors
++
+ std::vector<int> a5pos;
+
+ unsigned pos = 0;
+@@ -2875,6 +3035,14 @@ opt_shrink_stack_frame (void)
+ rtx pattern = PATTERN (ii.get_insn ());
+ if (ii.is_compare ())
+ pattern = XEXP(pattern, 1);
++
++ // lea n(sp),ax
++ if (ii.get_src_reg() && ii.get_src_regno () == STACK_POINTER_REGNUM && ii.get_src_op () == PLUS)
++ {
++ rtx src = XEXP(pattern, 1);
++ XEXP(src, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(src, 1)), ii.get_src_intval () - adjust);
++ }
++
+ if (ii.is_src_mem () && ii.is_src_mem_plus () && ii.get_src_mem_regno () == STACK_POINTER_REGNUM)
+ {
+ rtx src = XEXP(pattern, 1);
+@@ -2902,8 +3070,22 @@ opt_shrink_stack_frame (void)
+ log ("(f) dropping unused frame pointer\n");
+ for (std::vector<int>::reverse_iterator i = a5pos.rbegin (); i != a5pos.rend (); ++i)
+ {
+- SET_INSN_DELETED(infos[*i].get_insn ());
+- infos.erase (infos.begin () + *i);
++ unsigned index = *i;
++ SET_INSN_DELETED(infos[index].get_insn ());
++ while (index > 0 && infos[index].in_proepi () == 2)
++ --index;
++
++ insn_info & ii = infos[index];
++ if (!ii.in_proepi ())
++ {
++ if (ii.get_sp_offset () != 0)
++ {
++ log ("(f) adjusting exit sp\n");
++ rtx pattern = gen_rtx_SET(
++ a7, gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT(SImode, - ii.get_sp_offset())));
++ emit_insn_after (pattern, ii.get_insn ());
++ }
++ }
+ }
+
+ /* convert all parameter accesses via a5 into a7. */
+@@ -3157,7 +3339,7 @@ namespace
+ pass_bbb_optimizations::execute_bbb_optimizations (void)
+ {
+ be_very_verbose = strchr (string_bbb_opts, 'V');
+- be_verbose = be_very_verbose || strchr (string_bbb_opts, 'v');
++ be_verbose = be_very_verbose || strchr (string_bbb_opts, 'v') || 1;
+
+ bool do_opt_strcpy = strchr (string_bbb_opts, 's') || strchr (string_bbb_opts, '+');
+ bool do_commute_add_move = strchr (string_bbb_opts, 'a') || strchr (string_bbb_opts, '+');
+
+From 103cba07eca32f607fa4b9c6cce1ff757c9b97d4 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 24 May 2017 16:28:36 +0200
+Subject: [PATCH 136/303] @D disable verbose
+
+---
+ gcc/bbb-opts.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 43bcf138fc20..9dff55129ae3 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -3339,7 +3339,7 @@ namespace
+ pass_bbb_optimizations::execute_bbb_optimizations (void)
+ {
+ be_very_verbose = strchr (string_bbb_opts, 'V');
+- be_verbose = be_very_verbose || strchr (string_bbb_opts, 'v') || 1;
++ be_verbose = be_very_verbose || strchr (string_bbb_opts, 'v');
+
+ bool do_opt_strcpy = strchr (string_bbb_opts, 's') || strchr (string_bbb_opts, '+');
+ bool do_commute_add_move = strchr (string_bbb_opts, 'a') || strchr (string_bbb_opts, '+');
+
+From 3d84b641d630cd99c5ce14eeb42bc5307be3ffa8 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 24 May 2017 16:30:36 +0200
+Subject: [PATCH 137/303] @V bump date
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 301f35608896..8afbbd33cdaa 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170521
++20170524
+
+From a2ab0f8a257f6900e89d574ab8adf366fbd3d4a7 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 24 May 2017 20:06:02 +0200
+Subject: [PATCH 138/303] @B fix shrink stack frame - do not modify sp offsets
+ in prologue/epilogue
+
+---
+ gcc/bbb-opts.c | 16 ++++++++++------
+ 1 file changed, 10 insertions(+), 6 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 9dff55129ae3..bbbf02561fb4 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -1239,13 +1239,14 @@ append_reg_usage (FILE * f, rtx_insn * insn)
+ insn_info & ii = *i->second;
+
+ if (f != stderr)
+- fprintf (f, "\n\t\t\t\t\t\t|%c ", ii.is_stack () ? 's' : ' ');
++ fprintf (f, "\n\t\t\t\t\t\t|%c ",
++ ii.is_stack () ? 's' : ii.in_proepi () == 1 ? 'p' : ii.in_proepi () == 2 ? 'e' : ' ');
+
+ for (int j = 0; j < 8; ++j)
+ if (ii.is_use (j) || ii.is_def (j))
+ {
+ fprintf (f, ii.is_hard (j) ? "!" : " ");
+- fprintf (f, ii.is_def (j) ? ii.is_use (j) ? "*" : "+" : " ");
++ fprintf (f, ii.is_def (j) ? ii.is_use (j) ? "*" : "+" : ii.is_myuse (j) ? "." : " ");
+ fprintf (f, "d%d ", j);
+ }
+ else
+@@ -1255,7 +1256,7 @@ append_reg_usage (FILE * f, rtx_insn * insn)
+ if (ii.is_use (j) || ii.is_def (j))
+ {
+ fprintf (f, ii.is_hard (j) ? "!" : " ");
+- fprintf (f, ii.is_def (j) ? ii.is_use (j) ? "*" : "+" : " ");
++ fprintf (f, ii.is_def (j) ? ii.is_use (j) ? "*" : "+" : ii.is_myuse (j) ? "." : " ");
+ fprintf (f, "a%d ", j - 8);
+ }
+ else
+@@ -3032,12 +3033,15 @@ opt_shrink_stack_frame (void)
+ for (unsigned index = 0; index < infos.size (); ++index)
+ {
+ insn_info & ii = infos[index];
++ if (ii.in_proepi ())
++ continue;
++
+ rtx pattern = PATTERN (ii.get_insn ());
+ if (ii.is_compare ())
+ pattern = XEXP(pattern, 1);
+
+ // lea n(sp),ax
+- if (ii.get_src_reg() && ii.get_src_regno () == STACK_POINTER_REGNUM && ii.get_src_op () == PLUS)
++ if (ii.get_src_reg () && ii.get_src_regno () == STACK_POINTER_REGNUM && ii.get_src_op () == PLUS)
+ {
+ rtx src = XEXP(pattern, 1);
+ XEXP(src, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(src, 1)), ii.get_src_intval () - adjust);
+@@ -3049,13 +3053,13 @@ opt_shrink_stack_frame (void)
+ rtx plus = XEXP(src, 0);
+ if (ii.get_src_op ())
+ plus = XEXP(plus, 0);
+- XEXP(plus, 1) = gen_rtx_CONST_INT (SImode, ii.get_src_mem_addr () - adjust);
++ XEXP(plus, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(plus, 1)), ii.get_src_mem_addr () - adjust);
+ }
+
+ if (ii.is_dst_mem () && ii.is_dst_mem_plus () && ii.get_dst_mem_regno () == STACK_POINTER_REGNUM)
+ {
+ rtx plus = XEXP(XEXP(pattern, 0), 0);
+- XEXP(plus, 1) = gen_rtx_CONST_INT (SImode, ii.get_dst_intval () - adjust);
++ XEXP(plus, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(plus, 1)), ii.get_dst_intval () - adjust);
+ }
+ }
+ }
+
+From 948b24860fbecf6442f8d9dca3b932a951df57b1 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 26 May 2017 12:53:30 +0200
+Subject: [PATCH 139/303] @B fix inserting exit sp correction, @B fix parallel
+ pop if stack frame gets removed, @B fix patch only sp offsets referring to
+ local vars/params
+
+---
+ gcc/DATESTAMP | 2 +-
+ gcc/bbb-opts.c | 139 ++++++++++++++++++++++++++++++++++++++++++---------------
+ 2 files changed, 103 insertions(+), 38 deletions(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 8afbbd33cdaa..4d8890e894e9 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170524
++20170526
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index bbbf02561fb4..b716cf24a9a0 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -111,6 +111,11 @@ log (char const * fmt, ...)
+ return retval;
+ }
+
++enum proepis
++{
++ IN_CODE, IN_PROLOGUE, IN_EPILOGUE, IN_EPILOGUE_PARALLEL_POP
++};
++
+ /* Information for each insn to detect alive registers. Enough for m68k.
+ * Why a class? Maybe extend it for general usage.
+ *
+@@ -126,7 +131,7 @@ class insn_info
+ unsigned use; // bit set if registers are used in program flow
+ unsigned def; // bit set if registers are defined here
+
+- int proepi; // 1 = in prologue, 2 = in epilogue, 0 = other
++ enum proepis proepi;
+
+ bool stack; // part of stack frame insns
+
+@@ -163,7 +168,7 @@ class insn_info
+ int src_autoinc;
+
+ public:
+- insn_info (rtx_insn * i = 0, int p = 0) :
++ insn_info (rtx_insn * i = 0, enum proepis p = IN_CODE) :
+ insn (i), myuse (0), hard (0), use (0), def (0), proepi (p), stack (false), label (false), jump (false), call (
+ false), compare (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus (false), src_op (
+ (rtx_code) 0), src_ee (false), src_const (false), mode (VOIDmode), dst_reg (0), dst_mem_reg (0), dst_symbol (
+@@ -416,6 +421,12 @@ class insn_info
+ return proepi;
+ }
+
++ inline void
++ set_proepi (enum proepis p)
++ {
++ proepi = p;
++ }
++
+ inline void
+ reset_flags ()
+ {
+@@ -784,6 +795,9 @@ insn_info::scan_rtx (rtx x)
+ void
+ insn_info::fledder (rtx set)
+ {
++ if (GET_CODE(set) == PARALLEL)
++ return;
++
+ rtx dst = SET_DEST(set);
+ rtx src = SET_SRC(set);
+
+@@ -1239,8 +1253,10 @@ append_reg_usage (FILE * f, rtx_insn * insn)
+ insn_info & ii = *i->second;
+
+ if (f != stderr)
+- fprintf (f, "\n\t\t\t\t\t\t|%c ",
+- ii.is_stack () ? 's' : ii.in_proepi () == 1 ? 'p' : ii.in_proepi () == 2 ? 'e' : ' ');
++ fprintf (f, "\n\t\t\t\t\t\t|");
++
++ fprintf (f, "%c ",
++ ii.is_stack () ? 's' : ii.in_proepi () == IN_PROLOGUE ? 'p' : ii.in_proepi () >= IN_EPILOGUE ? 'e' : ' ');
+
+ for (int j = 0; j < 8; ++j)
+ if (ii.is_use (j) || ii.is_def (j))
+@@ -1336,7 +1352,7 @@ update_insn_infos (void)
+ continue;
+
+ /* no new information -> break. */
+- if (pp.in_proepi () == 0 && pp.is_visited () && pp.contains (ii))
++ if (pp.in_proepi () == IN_CODE && pp.is_visited () && pp.contains (ii))
+ break;
+
+ ii.clear_hard_def ();
+@@ -1393,7 +1409,7 @@ update_insn_infos (void)
+ }
+
+ /* mark not renameable in prologue/epilogue. */
+- if (infos[pos].in_proepi ())
++ if (infos[pos].in_proepi () != IN_CODE)
+ use.make_hard ();
+
+ ii.merge (use);
+@@ -1407,7 +1423,7 @@ update_insn_infos (void)
+ for (unsigned i = 0; i < infos.size (); ++i)
+ {
+ insn_info & ii = infos[i];
+- if (ii.in_proepi () != 1)
++ if (ii.in_proepi () != IN_PROLOGUE)
+ break;
+
+ zz.or_use (ii);
+@@ -1441,7 +1457,7 @@ update_insns ()
+
+ clear ();
+
+- char inproepilogue = 1;
++ enum proepis inproepilogue = IN_PROLOGUE;
+ /* create a vector with relevant insn. */
+ for (insn = get_insns (); insn; insn = next)
+ {
+@@ -1458,7 +1474,7 @@ update_insns ()
+ if (inproepilogue || ANY_RETURN_P(PATTERN (insn)))
+ {
+ returns.insert (infos.size () - 1);
+- inproepilogue = 0;
++ inproepilogue = IN_CODE;
+ if (ANY_RETURN_P(PATTERN (insn)))
+ continue;
+ }
+@@ -1548,9 +1564,9 @@ update_insns ()
+ else if (NOTE_P(insn))
+ {
+ if (NOTE_KIND(insn) == NOTE_INSN_PROLOGUE_END)
+- inproepilogue = 0;
++ inproepilogue = IN_CODE;
+ else if (NOTE_KIND(insn) == NOTE_INSN_EPILOGUE_BEG)
+- inproepilogue = 2;
++ inproepilogue = IN_EPILOGUE;
+ }
+ }
+
+@@ -2590,7 +2606,7 @@ track_sp ()
+ for (unsigned index = startpos; index < infos.size (); ++index)
+ {
+ insn_info & ii = infos[index];
+- if (ii.in_proepi ())
++ if (ii.in_proepi () != IN_CODE)
+ continue;
+
+ // already visited? sp_offset must match
+@@ -2624,7 +2640,7 @@ track_sp ()
+ if (ii.is_dst_reg () && ii.get_dst_regno () == STACK_POINTER_REGNUM)
+ {
+ // handle sp = sp + const_int
+- if (!ii.is_src_reg () || ii.get_src_regno () != STACK_POINTER_REGNUM || ii.get_src_op () != PLUS)
++ if (!ii.get_src_reg () || ii.get_src_regno () != STACK_POINTER_REGNUM || ii.get_src_op () != PLUS)
+ return E_SP_MISMATCH;
+
+ sp_offset = sp_offset + ii.get_src_intval ();
+@@ -2698,7 +2714,7 @@ opt_shrink_stack_frame (void)
+ insn_info & ii = infos[pos];
+ insn = ii.get_insn ();
+
+- if (ii.in_proepi () != 1)
++ if (ii.in_proepi () != IN_PROLOGUE)
+ break;
+
+ rtx pattern = PATTERN (insn);
+@@ -2770,7 +2786,7 @@ opt_shrink_stack_frame (void)
+ {
+ while (pos < infos.size ())
+ {
+- if (infos[pos].in_proepi ())
++ if (infos[pos].in_proepi () != IN_CODE)
+ break;
+ ++pos;
+ }
+@@ -2780,7 +2796,7 @@ opt_shrink_stack_frame (void)
+ {
+ insn_info & ii = infos[pos];
+ insn = ii.get_insn ();
+- if (JUMP_P(insn) || LABEL_P(insn) || !ii.in_proepi ())
++ if (JUMP_P(insn) || LABEL_P(insn) || ii.in_proepi () == IN_CODE)
+ break;
+
+ /* omit the frame pointer a5. */
+@@ -2831,7 +2847,7 @@ opt_shrink_stack_frame (void)
+ for (unsigned i = 0; i < infos.size (); ++i)
+ {
+ insn_info & jj = infos[i];
+- if (jj.in_proepi ())
++ if (jj.in_proepi () == IN_CODE)
+ continue;
+
+ ii.or_use (jj);
+@@ -2843,6 +2859,8 @@ opt_shrink_stack_frame (void)
+
+ unsigned changed = 0;
+ unsigned adjust = 0;
++ unsigned regs_seen = 0;
++ unsigned regs_total_size = 0;
+ /* now all push/pop insns are in temp. */
+ for (unsigned i = 0; i < infos.size (); ++i)
+ {
+@@ -2861,6 +2879,11 @@ opt_shrink_stack_frame (void)
+ if (REG_P(dst) && REGNO(dst) == FRAME_POINTER_REGNUM)
+ continue;
+
++ if (ii.in_proepi () == IN_EPILOGUE)
++ ii.set_proepi (IN_EPILOGUE_PARALLEL_POP);
++
++ regs_seen = 0;
++ regs_total_size = 0;
+ std::vector<rtx> regs;
+ std::vector<rtx> clobbers;
+ for (int j = 0; j < XVECLEN(pattern, 0); ++j)
+@@ -2884,15 +2907,20 @@ opt_shrink_stack_frame (void)
+ if (i < prologueend)
+ paramstart += 4;
+ unsigned regbit = 1 << REGNO(reg);
++
++ ++regs_seen;
+ if (freemask & regbit)
+ {
+ log (i < prologueend ? "(f) remove push for %s\n" : "(f) remove pop for %s\n",
+ reg_names[REGNO(reg)]);
+ if (i < prologueend)
+- adjust += 4;
++ adjust += GET_MODE_SIZE(GET_MODE(reg));
+ }
+ else
+- regs.push_back (copy_reg (reg, -1));
++ {
++ regs_total_size += GET_MODE_SIZE(GET_MODE(reg));
++ regs.push_back (copy_reg (reg, -1));
++ }
+ }
+
+ /* add room for add.
+@@ -2901,10 +2929,9 @@ opt_shrink_stack_frame (void)
+ * Otherwise a7 is used and with (a7)+ addressing.
+ */
+ int add1 = i < prologueend || !usea5 ? 1 : 0;
+- if ((int) regs.size () + add1 + (int) clobbers.size () < XVECLEN(pattern, 0) || regs.size () <= 2)
++ if (regs.size () < regs_seen)
+ {
+- log ("(f) shrinking stack frame from %d to %d\n", XVECLEN(pattern, 0) - add1 - clobbers.size (),
+- regs.size ());
++ log ("(f) shrinking stack frame from %d to %d\n", regs_seen, regs.size ());
+ if (regs.size () <= 2)
+ {
+ changed = 1;
+@@ -3033,7 +3060,7 @@ opt_shrink_stack_frame (void)
+ for (unsigned index = 0; index < infos.size (); ++index)
+ {
+ insn_info & ii = infos[index];
+- if (ii.in_proepi ())
++ if (ii.in_proepi () != IN_CODE)
+ continue;
+
+ rtx pattern = PATTERN (ii.get_insn ());
+@@ -3043,11 +3070,14 @@ opt_shrink_stack_frame (void)
+ // lea n(sp),ax
+ if (ii.get_src_reg () && ii.get_src_regno () == STACK_POINTER_REGNUM && ii.get_src_op () == PLUS)
+ {
+- rtx src = XEXP(pattern, 1);
+- XEXP(src, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(src, 1)), ii.get_src_intval () - adjust);
++ // touch only if above pushed parameters
++ if (ii.get_src_intval () > -ii.get_sp_offset ())
++ {
++ rtx src = XEXP(pattern, 1);
++ XEXP(src, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(src, 1)), ii.get_src_intval () - adjust);
++ }
+ }
+-
+- if (ii.is_src_mem () && ii.is_src_mem_plus () && ii.get_src_mem_regno () == STACK_POINTER_REGNUM)
++ else if (ii.is_src_mem () && ii.is_src_mem_plus () && ii.get_src_mem_regno () == STACK_POINTER_REGNUM)
+ {
+ rtx src = XEXP(pattern, 1);
+ rtx plus = XEXP(src, 0);
+@@ -3076,19 +3106,18 @@ opt_shrink_stack_frame (void)
+ {
+ unsigned index = *i;
+ SET_INSN_DELETED(infos[index].get_insn ());
+- while (index > 0 && infos[index].in_proepi () == 2)
++
++ // move to last insn in epilogue
++ while (index - 1 > 0 && infos[index - 1].in_proepi () >= IN_EPILOGUE)
+ --index;
+
+ insn_info & ii = infos[index];
+- if (!ii.in_proepi ())
++ if (ii.get_sp_offset () != 0)
+ {
+- if (ii.get_sp_offset () != 0)
+- {
+- log ("(f) adjusting exit sp\n");
+- rtx pattern = gen_rtx_SET(
+- a7, gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT(SImode, - ii.get_sp_offset())));
+- emit_insn_after (pattern, ii.get_insn ());
+- }
++ log ("(f) adjusting exit sp\n");
++ rtx pattern = gen_rtx_SET(a7,
++ gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT(SImode, - ii.get_sp_offset())));
++ emit_insn_before (pattern, ii.get_insn ());
+ }
+ }
+
+@@ -3097,7 +3126,43 @@ opt_shrink_stack_frame (void)
+ {
+ insn_info & ii = infos[i];
+ if (ii.get_myuse () & (1 << FRAME_POINTER_REGNUM))
+- ii.a5_to_a7 (a7);
++ {
++ ii.a5_to_a7 (a7);
++ if (regs_seen && ii.in_proepi () == IN_EPILOGUE_PARALLEL_POP)
++ {
++ // exit sp insn needs an +
++ rtx pattern = PATTERN (ii.get_insn ());
++ unsigned sz = XVECLEN(pattern, 0);
++
++ rtx parallel = gen_rtx_PARALLEL(VOIDmode, rtvec_alloc (sz + 1));
++ unsigned n = 0;
++ for (unsigned j = 0; j < sz; ++j)
++ {
++ rtx set = XVECEXP(pattern, 0, j);
++ rtx reg = SET_DEST(set);
++ rtx mem = SET_SRC(set);
++ rtx plus = XEXP(mem, 0);
++ if (n)
++ {
++ XEXP(plus, 1) = gen_rtx_CONST_INT (SImode, n);
++ }
++ else
++ {
++ XEXP(mem, 0) = XEXP(plus, 0);
++ }
++ n += GET_MODE_SIZE(GET_MODE(reg));
++ XVECEXP(parallel, 0, j + 1) = set;
++ }
++
++ rtx a = copy_reg (a7, -1);
++ a->frame_related = 1;
++ rtx plus = gen_rtx_PLUS(SImode, a, gen_rtx_CONST_INT (SImode, regs_total_size));
++ rtx set = gen_rtx_SET(a, plus);
++ XVECEXP(parallel, 0, 0) = set;
++ SET_INSN_DELETED(ii.get_insn ());
++ ii.set_insn (emit_insn_after (parallel, ii.get_insn ()));
++ }
++ }
+
+ ii.unset (FRAME_POINTER_REGNUM);
+ }
+
+From 0c94ad510c11dbd020d66482ac4ef28857f86d2e Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 26 May 2017 21:20:04 +0200
+Subject: [PATCH 140/303] @B fix flow recog loop
+
+---
+ gcc/bbb-opts.c | 50 +++++++++++++++++++++++++++++++++++---------------
+ 1 file changed, 35 insertions(+), 15 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index b716cf24a9a0..6b1a6bb5f3c0 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -177,6 +177,12 @@ class insn_info
+ {
+ }
+
++ inline ptrdiff_t
++ operator < (insn_info const & o) const
++ {
++ return this - &o;
++ }
++
+ int
+ get_index () const;
+
+@@ -1329,21 +1335,20 @@ static void
+ update_insn_infos (void)
+ {
+ /* add all return (jump outs) and start analysis there. */
+- std::vector<std::pair<unsigned, insn_info> > todo;
++ std::set<unsigned> todo;
+ for (su_iterator i = returns.begin (); i != returns.end (); ++i)
+- todo.push_back (std::make_pair (*i, insn_info ()));
++ todo.insert (*i);
+
+ if (todo.begin () == todo.end ())
+- todo.push_back (std::make_pair (infos.size () - 1, insn_info ()));
++ todo.insert (infos.size () - 1);
+
+ while (!todo.empty ())
+ {
+- std::pair<unsigned, insn_info> p = *todo.rbegin ();
+- todo.pop_back ();
++ int start = *todo.begin ();
++ todo.erase (todo.begin ());
++ insn_info ii = infos[start];
+
+- insn_info ii = p.second;
+-
+- for (int pos = p.first; pos >= 0; --pos)
++ for (int pos = start; pos >= 0; --pos)
+ {
+ insn_info & pp = infos[pos];
+ rtx_insn * insn = pp.get_insn ();
+@@ -1352,7 +1357,7 @@ update_insn_infos (void)
+ continue;
+
+ /* no new information -> break. */
+- if (pp.in_proepi () == IN_CODE && pp.is_visited () && pp.contains (ii))
++ if (pos != start && pp.is_visited () && !JUMP_P(insn) && pp.contains (ii))
+ break;
+
+ ii.clear_hard_def ();
+@@ -1366,8 +1371,20 @@ update_insn_infos (void)
+ {
+ i2i_iterator j = insn2info.find (i->second);
+ if (j != insn2info.end ())
+- todo.push_back (std::make_pair (j->second->get_index (), ii));
++ {
++ unsigned index = j->second->get_index ();
++ insn_info & jj = infos[index];
++ if (!jj.is_visited () || !jj.contains (ii))
++ {
++ jj.updateWith (ii);
++ todo.insert (index);
++ }
++ }
+ }
++
++ if (pos == start)
++ pp.mark_visited ();
++// pp.update (ii);
+ continue;
+ }
+
+@@ -1382,7 +1399,7 @@ update_insn_infos (void)
+ }
+ else if (JUMP_P(insn))
+ {
+- if ((unsigned) pos != p.first)
++ if (pos != start)
+ {
+ su_iterator k = returns.find (pos);
+ if (k != returns.end ())
+@@ -2607,7 +2624,10 @@ track_sp ()
+ {
+ insn_info & ii = infos[index];
+ if (ii.in_proepi () != IN_CODE)
+- continue;
++ {
++ ii.set_sp_offset (sp_offset);
++ continue;
++ }
+
+ // already visited? sp_offset must match
+ if (ii.is_visited ())
+@@ -2847,7 +2867,7 @@ opt_shrink_stack_frame (void)
+ for (unsigned i = 0; i < infos.size (); ++i)
+ {
+ insn_info & jj = infos[i];
+- if (jj.in_proepi () == IN_CODE)
++ if (jj.in_proepi () != IN_CODE)
+ continue;
+
+ ii.or_use (jj);
+@@ -3104,7 +3124,7 @@ opt_shrink_stack_frame (void)
+ log ("(f) dropping unused frame pointer\n");
+ for (std::vector<int>::reverse_iterator i = a5pos.rbegin (); i != a5pos.rend (); ++i)
+ {
+- unsigned index = *i;
++ int index = *i;
+ SET_INSN_DELETED(infos[index].get_insn ());
+
+ // move to last insn in epilogue
+@@ -3112,7 +3132,7 @@ opt_shrink_stack_frame (void)
+ --index;
+
+ insn_info & ii = infos[index];
+- if (ii.get_sp_offset () != 0)
++ if (ii.in_proepi () >= IN_EPILOGUE && ii.get_sp_offset () != 0)
+ {
+ log ("(f) adjusting exit sp\n");
+ rtx pattern = gen_rtx_SET(a7,
+
+From aea30fb817d7af78317be6f363975ef30a56129b Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sat, 27 May 2017 00:33:52 +0200
+Subject: [PATCH 141/303] @R disabled soft float in gcc
+
+---
+ .project | 7 +++++++
+ .settings/language.settings.xml | 2 +-
+ libgcc/config.host | 3 ++-
+ 3 files changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/.project b/.project
+index 22b8c5a11f48..500c9ee08dca 100644
+--- .project
++++ .project
+@@ -24,4 +24,11 @@
+ <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+ <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+ </natures>
++ <linkedResources>
++ <link>
++ <name>build-gcc</name>
++ <type>2</type>
++ <location>D:/develop/workspaces/c1/amigaos-cross-toolchain/.build-m68k/build/gcc-6</location>
++ </link>
++ </linkedResources>
+ </projectDescription>
+diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml
+index c6ac9211311a..caef162d88d1 100755
+--- .settings/language.settings.xml
++++ .settings/language.settings.xml
+@@ -16,7 +16,7 @@
+ <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
+ <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
+ <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
+- <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="860895942062206931" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
++ <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-910044784883564564" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
+ <language-scope id="org.eclipse.cdt.core.gcc"/>
+ <language-scope id="org.eclipse.cdt.core.g++"/>
+ </provider>
+diff --git a/libgcc/config.host b/libgcc/config.host
+index 2eb982df6274..f456ff689ad9 100644
+--- libgcc/config.host
++++ libgcc/config.host
+@@ -817,7 +817,8 @@ m32rle-*-linux*)
+ tmake_file="$tmake_file m32r/t-linux t-fdpbit"
+ ;;
+ m68k-*-amiga*)
+- tmake_file="$tmake_file m68k/t-floatlib"
++ tmake_file="$tmake_file
++# m68k/t-floatlib"
+ ;;
+ m68k-*-elf* | fido-*-elf)
+ tmake_file="$tmake_file m68k/t-floatlib"
+
+From 22166a8c54eedddc7f3bb718c3be733dae48d367 Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Sat, 27 May 2017 13:35:18 +0100
+Subject: [PATCH 142/303] @V bump datestamp
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 4d8890e894e9..3042ace073af 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170526
++20170527-133518
+
+From bdc1872397c7c616974499050001710681d3346e Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Sat, 27 May 2017 13:50:12 +0100
+Subject: [PATCH 143/303] @V bump datestamp
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 3042ace073af..cb171356c5e5 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170527-133518
++20170527-135012
+
+From 497b371bb123e18aa03089ff176b991be46a4324 Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Sat, 27 May 2017 15:14:21 +0100
+Subject: [PATCH 144/303] @V bump datestamp
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index cb171356c5e5..3ebdd3995a41 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170527-135012
++20170527-151421
+
+From 40c89d195204d51e61d08bdd7f0d10b5f1b64db7 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sat, 27 May 2017 23:28:12 +0200
+Subject: [PATCH 145/303] @R fixes for TARGET_AMIGAOS_VASM
+
+---
+ gcc/config/m68k/m68k.c | 13 +++++++++
+ gcc/config/m68k/m68kamigaos.h | 61 ++++++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 73 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
+index 3b51b2541bc9..d123cc065c18 100644
+--- gcc/config/m68k/m68k.c
++++ gcc/config/m68k/m68k.c
+@@ -4593,20 +4593,33 @@ print_operand (FILE *file, rtx op, int letter)
+ {
+ long l;
+ REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (op), l);
++#ifndef TARGET_AMIGAOS_VASM
+ asm_fprintf (file, "%I0x%lx", l & 0xFFFFFFFF);
++#else
++ asm_fprintf (file, "%I$%lx", l & 0xFFFFFFFF);
++#endif
+ }
+ else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == XFmode)
+ {
+ long l[3];
+ REAL_VALUE_TO_TARGET_LONG_DOUBLE (*CONST_DOUBLE_REAL_VALUE (op), l);
++#ifndef TARGET_AMIGAOS_VASM
+ asm_fprintf (file, "%I0x%lx%08lx%08lx", l[0] & 0xFFFFFFFF,
+ l[1] & 0xFFFFFFFF, l[2] & 0xFFFFFFFF);
++#else
++ asm_fprintf (file, "%I$%lx%08lx%08lx", l[0] & 0xFFFFFFFF,
++ l[1] & 0xFFFFFFFF, l[2] & 0xFFFFFFFF);
++#endif
+ }
+ else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == DFmode)
+ {
+ long l[2];
+ REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (op), l);
++#ifndef TARGET_AMIGAOS_VASM
+ asm_fprintf (file, "%I0x%lx%08lx", l[0] & 0xFFFFFFFF, l[1] & 0xFFFFFFFF);
++#else
++ asm_fprintf (file, "%I$%lx%08lx", l[0] & 0xFFFFFFFF, l[1] & 0xFFFFFFFF);
++#endif
+ }
+ else
+ {
+diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h
+index a81007bb15d5..aabd0ab5e521 100644
+--- gcc/config/m68k/m68kamigaos.h
++++ gcc/config/m68k/m68kamigaos.h
+@@ -31,6 +31,17 @@ along with GCC; see the file COPYING3. If not see
+ #define SWBEG_ASM_OP "\t.swbeg\t"
+ #endif
+
++#ifdef TARGET_AMIGAOS_VASM
++#undef ASM_STABS_OP
++#define ASM_STABS_OP "|\t.stabs\t"
++
++#undef ASM_STABD_OP
++#define ASM_STABD_OP "|\t.stabd\t"
++
++#undef ASM_STABN_OP
++#define ASM_STABN_OP "|\t.stabn\t"
++#endif
++
+ #undef PIC_REG
+ #define PIC_REG 12
+
+@@ -410,11 +421,16 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ ")"
+
+ #undef STARTFILE_SPEC
++#ifdef TARGET_AMIGAOS_VASM
++#define STARTFILE_SPEC \
++ "startup%O%s"
++#else
+ #define STARTFILE_SPEC \
+ "%{noixemul:%(startfile_libnix)} " \
+ "%{mcrt=nix*:%(startfile_libnix)} " \
+ "%{mcrt=ixemul:%(startfile_ixemul)} " \
+ "%{mcrt=clib2:%(startfile_clib2)}"
++#endif
+
+ #define ENDFILE_IXEMUL_SPEC ""
+ #define ENDFILE_LIBNIX_SPEC "-lstubs"
+@@ -456,11 +472,16 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ "%{mstackcheck:-lstack} " \
+ "%{mstackextend:-lstack}"
+
++#ifdef TARGET_AMIGAOS_VASM
++#define LIB_SPEC \
++ "-lvc -lamiga "
++#else
+ #define LIB_SPEC \
+ "%{noixemul:%(lib_libnix)} " \
+ "%{mcrt=nix*:%(lib_libnix)} " \
+ "%{mcrt=ixemul:%(lib_ixemul)} " \
+ "%{mcrt=clib2:%(lib_clib2)}"
++#endif
+
+ #define LIBGCC_IXEMUL_SPEC ""
+ #define LIBGCC_LIBNIX_SPEC "-lnix -fl libnix " \
+@@ -487,7 +508,26 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ Also, pass appropriate linker flavours depending on user-supplied
+ commandline options. */
+
++#ifdef TARGET_AMIGAOS_VASM
+ #define LINK_SPEC \
++ "%{noixemul:%(link_libnix)} " \
++ "%{mcrt=nix*:%(link_libnix)} " \
++ "%{mcrt=ixemul:%(link_ixemul)} " \
++ "%{mcrt=clib2:%(link_clib2)} " \
++ "%{fbaserel:%{!resident:-m amiga_bss -fl libb %{noixemul:-fl libnix} %{mcrt=nix*:-fl libnix}}} " \
++ "%{resident:-m amiga_bss -amiga-datadata-reloc -fl libb %{noixemul:-fl libnix} %{mcrt=nix*:-fl libnix}} " \
++ "%{fbaserel32:%{!resident32:-m amiga_bss -fl libb32 %{noixemul:-fl libnix} %{mcrt=nix*:-fl libnix}}} " \
++ "%{resident32:-m amiga_bss -amiga-datadata-reloc -fl libb32 %{noixemul:-fl libnix} %{mcrt=nix*:-fl libnix}} " \
++ "%{mcpu=68020:-fl libm020} " \
++ "%{m68020:-fl libm020} " \
++ "%{mc68020:-fl libm020} " \
++ "%{m68030:-fl libm020} " \
++ "%{m68040:-fl libm020} " \
++ "%{m68060:-fl libm020} " \
++ "%{m68020-40:-fl libm020} " \
++ "%{m68020-60:-fl libm020} " \
++ "%{m68881:-fl libm881}"
++#else
+ "%{noixemul:%(link_libnix)} " \
+ "%{mcrt=nix*:%(link_libnix)} " \
+ "%{mcrt=ixemul:%(link_ixemul)} " \
+@@ -506,6 +546,7 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ "%{m68020-40:-fl libm020} " \
+ "%{m68020-60:-fl libm020} " \
+ "%{m68881:-fl libm881}"
++#endif
+
+ /* Translate '-resident' to '-fbaserel' (they differ in linking stage only).
+ Don't put function addresses in registers for PC-relative code. */
+@@ -524,6 +565,23 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ at the end of command line. Otherwise linker chooses generic functions
+ from libgcc.a instead AmigaOS-specific counterparts from libnix.a. */
+
++#ifdef TARGET_AMIGAOS_VASM
++#define LINK_COMMAND_SPEC \
++ "%{!fsyntax-only:" \
++ "%{!c:" \
++ "%{!M:" \
++ "%{!MM:" \
++ "%{!E:" \
++ "%{!S:" \
++ "%(linker) -Cvbcc %l %X %{o*} %{A} %{d} %{e*} %{m} " \
++ "%{N} %{n} %{r} %{s} %{t} %{u*} %{x} %{z} %{Z} " \
++ "%{!A:%{!nostdlib:%{!nostartfiles:%S}}} " \
++ "%{static:} %{L*} %D %o " \
++ "%{!nostdlib:%{!nodefaultlibs:%L}} " \
++ "%{!A:%{!nostdlib:%{!nostartfiles:%E}}} " \
++ "%{!nostdlib:%{!nodefaultlibs:%G}} " \
++ "%{T*} }}}}}} "
++#else
+ #define LINK_COMMAND_SPEC \
+ "%{!fsyntax-only:" \
+ "%{!c:" \
+@@ -538,7 +596,8 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ "%{!nostdlib:%{!nodefaultlibs:%L}} " \
+ "%{!A:%{!nostdlib:%{!nostartfiles:%E}}} " \
+ "%{!nostdlib:%{!nodefaultlibs:%G}} " \
+- "%{T*} }}}}}} " \
++ "%{T*} }}}}}} "
++#endif
+
+ extern const char * amiga_m68k_prefix_func(int, const char **);
+
+
+From f86473acc971c74d399d0b0f7de418ab45a9cd46 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 28 May 2017 07:12:48 +0200
+Subject: [PATCH 146/303] @B fix defines
+
+---
+ gcc/config/m68k/m68kamigaos.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h
+index aabd0ab5e521..a286fff9c688 100644
+--- gcc/config/m68k/m68kamigaos.h
++++ gcc/config/m68k/m68kamigaos.h
+@@ -528,6 +528,7 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ "%{m68020-60:-fl libm020} " \
+ "%{m68881:-fl libm881}"
+ #else
++#define LINK_SPEC \
+ "%{noixemul:%(link_libnix)} " \
+ "%{mcrt=nix*:%(link_libnix)} " \
+ "%{mcrt=ixemul:%(link_ixemul)} " \
+
+From 205a71781ce9bd12d9360462dfcb7e87bacc382b Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Sun, 28 May 2017 06:24:32 +0100
+Subject: [PATCH 147/303] @V bump datestamp
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 3ebdd3995a41..12703d9cab62 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170527-151421
++20170528-062432
+
+From 208ca25348e2fe8597be046ba1e841e5cddb5448 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 28 May 2017 20:39:12 +0200
+Subject: [PATCH 148/303] @I use set instead of vector to track the stack
+ pointer
+
+---
+ gcc/bbb-opts.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 6b1a6bb5f3c0..db1d1b6b369e 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -2610,13 +2610,13 @@ track_sp ()
+ }
+
+ // add entry point
+- std::vector<unsigned> todo;
+- todo.push_back (0);
++ std::set<unsigned> todo;
++ todo.insert (0);
+
+- while (todo.size () > 0)
++ while (todo.begin () != todo.end ())
+ {
+- unsigned startpos = todo[todo.size () - 1];
+- todo.pop_back ();
++ unsigned startpos = *todo.begin ();
++ todo.erase (todo.begin ());
+
+ int sp_offset = infos[startpos].get_sp_offset ();
+
+@@ -2651,7 +2651,7 @@ track_sp ()
+ return E_SP_MISMATCH;
+
+ ll.set_sp_offset (sp_offset);
+- todo.push_back (i->second);
++ todo.insert (i->second);
+ }
+ continue;
+ }
+
+From 8f616d112701133d7bafb8db6dceb6895eead852 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 29 May 2017 11:31:30 +0200
+Subject: [PATCH 149/303] @I improved reg usage tracking and reg renaming
+
+---
+ gcc/bbb-opts.c | 43 ++++++++++++++++++++++++++++++-------------
+ 1 file changed, 30 insertions(+), 13 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index db1d1b6b369e..0b71eef7d5c0 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -677,15 +677,19 @@ class insn_info
+ if (def & hard)
+ return 0;
+
+- if (!def || (def & ~(1 << FIRST_PSEUDO_REGISTER)) > 0x1000)
++ if (!def)
+ return 0;
+
+- unsigned mask = def - 1;
++ unsigned def_no_cc = def & ~(1 << FIRST_PSEUDO_REGISTER);
++ if (def_no_cc > 0x4000)
++ return 0;
++
++ unsigned mask = def_no_cc - 1;
+ /* more than one register -> don't touch. */
+ if ((mask & ~def) != mask)
+ return 0;
+
+- if (def > 0xff)
++ if (def_no_cc > 0xff)
+ mask &= 0xff00;
+
+ return mask & ~use;
+@@ -1384,7 +1388,17 @@ update_insn_infos (void)
+
+ if (pos == start)
+ pp.mark_visited ();
+-// pp.update (ii);
++
++ /* check previous insn for jump */
++ if (pos > 0 && infos[pos - 1].is_jump ())
++ {
++ rtx_insn * prev = infos[pos - 1].get_insn ();
++ rtx set = single_set (prev);
++ /* unconditional? -> break! */
++ if (set && SET_DEST(set) == pc_rtx && GET_CODE(SET_SRC(set)) != IF_THEN_ELSE)
++ break;
++ }
++
+ continue;
+ }
+
+@@ -1492,7 +1506,9 @@ update_insns ()
+ {
+ returns.insert (infos.size () - 1);
+ inproepilogue = IN_CODE;
+- if (ANY_RETURN_P(PATTERN (insn)))
++ rtx set = single_set (insn);
++ if (ANY_RETURN_P(PATTERN (insn))
++ || (set && SET_DEST(set) == pc_rtx && GET_CODE(SET_SRC(set)) != IF_THEN_ELSE))
+ continue;
+ }
+
+@@ -1556,6 +1572,7 @@ update_insns ()
+ {
+ ii.mark_label ();
+ jump_table = 0;
++ ii.set_proepi(inproepilogue = IN_CODE);
+ }
+ else if (CALL_P(insn))
+ {
+@@ -1677,17 +1694,17 @@ opt_reg_rename (void)
+ continue;
+
+ /* first = pos to start, second indicates to treat def as use. */
+- std::vector<unsigned> todo;
++ std::set<unsigned> todo;
+ std::set<unsigned> found;
+ if (index + 1 < infos.size ())
+- todo.push_back (index + 1);
++ todo.insert (index + 1);
+
+ found.insert (index);
+ /* a register was defined, follow all branches. */
+- while (mask && todo.size ())
++ while (mask && todo.begin () != todo.end ())
+ {
+- unsigned runpos = todo[todo.size () - 1];
+- todo.pop_back ();
++ unsigned runpos = *todo.begin ();
++ todo.erase (todo.begin ());
+
+ for (unsigned pos = runpos; mask && pos < infos.size (); ++pos)
+ {
+@@ -1716,7 +1733,7 @@ opt_reg_rename (void)
+ continue;
+
+ start = find_start (found, start, rename_regno);
+- todo.push_back (start);
++ todo.insert (start);
+ }
+ continue;
+ }
+@@ -1774,9 +1791,9 @@ opt_reg_rename (void)
+ if (bb.is_use (rename_regno))
+ {
+ unsigned start = find_start (found, label_index, rename_regno);
+- todo.push_back (start);
++ todo.insert (start);
+ }
+- todo.push_back (label_index + 1);
++ todo.insert (label_index + 1);
+ }
+ rtx jmppattern = PATTERN (insn);
+ if (GET_CODE(jmppattern) == PARALLEL)
+
+From 19cecc88e679fc1926df66fc4df5feaaaa4fce63 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 29 May 2017 20:25:44 +0200
+Subject: [PATCH 150/303] @B #25 cpu defaults now to m68000 (was m68040)
+
+---
+ gcc/config/m68k/m68kamigaos.h | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h
+index a286fff9c688..8a25f8cbfdfb 100644
+--- gcc/config/m68k/m68kamigaos.h
++++ gcc/config/m68k/m68kamigaos.h
+@@ -367,7 +367,8 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ #endif
+
+ #undef ASM_CPU_SPEC
+-#define ASM_CPU_SPEC \
++#define ASM_CPU_SPEC \
++ "%{mcpu=*:-m%*} " \
+ "%{m68000|mc68000:-m68010} " \
+ "%{m6802*|mc68020:-m68020} " \
+ "%{m68030} " \
+@@ -376,7 +377,7 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+
+ #ifndef TARGET_AMIGAOS_VASM
+ #define ASM_CPU_DEFAULT_SPEC \
+- "%{!m680*:%{!mc680*:-m68040}}"
++ "%{!m680*:%{!mc680*:%{!mcpu=*:-m68000}}}"
+ #else
+ #define ASM_CPU_DEFAULT_SPEC \
+ "%{!m680*:%{!mc680*:-m68000}}"
+
+From f6cdedb91a27adc4aa437490c846d0863550b011 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 29 May 2017 20:27:07 +0200
+Subject: [PATCH 151/303] @B fix handling parallel insns with set + clobber
+
+---
+ gcc/bbb-opts.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 0b71eef7d5c0..a76b70385d9c 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -805,7 +805,7 @@ insn_info::scan_rtx (rtx x)
+ void
+ insn_info::fledder (rtx set)
+ {
+- if (GET_CODE(set) == PARALLEL)
++ if (!set || GET_CODE(set) == PARALLEL)
+ return;
+
+ rtx dst = SET_DEST(set);
+@@ -1142,13 +1142,13 @@ insn_info::set_insn (rtx_insn * newinsn)
+
+ reset_flags ();
+
+- fledder (PATTERN (insn));
++ fledder (single_set (insn));
+ }
+
+ void
+ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol)
+ {
+- rtx set = PATTERN (get_insn ());
++ rtx set = single_set (get_insn ());
+ rtx src = SET_SRC(set);
+ rtx dst = SET_DEST(set);
+
+@@ -1572,7 +1572,7 @@ update_insns ()
+ {
+ ii.mark_label ();
+ jump_table = 0;
+- ii.set_proepi(inproepilogue = IN_CODE);
++ ii.set_proepi (inproepilogue = IN_CODE);
+ }
+ else if (CALL_P(insn))
+ {
+@@ -3100,7 +3100,7 @@ opt_shrink_stack_frame (void)
+ if (ii.in_proepi () != IN_CODE)
+ continue;
+
+- rtx pattern = PATTERN (ii.get_insn ());
++ rtx pattern = single_set (ii.get_insn ());
+ if (ii.is_compare ())
+ pattern = XEXP(pattern, 1);
+
+
+From 5ab0b26c5f50357a306188c7348c818136106b19 Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Mon, 29 May 2017 21:58:32 +0100
+Subject: [PATCH 152/303] @V bump DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 4d8890e894e9..b5d1e40685b6 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170526
++20170529-215512
+
+From fb1df368db776fcc6091421a2b538b346ffccad0 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 30 May 2017 19:03:36 +0200
+Subject: [PATCH 153/303] @B jumps inside epilogue which result from chained
+ calls are still CALL insns...
+
+---
+ gcc/bbb-opts.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index a76b70385d9c..a187666945f0 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -1408,10 +1408,7 @@ update_insn_infos (void)
+ insn_info use (insn);
+ use.scan ();
+
+- if (CALL_P(insn))
+- {
+- }
+- else if (JUMP_P(insn))
++ if (CALL_P(insn) || JUMP_P(insn))
+ {
+ if (pos != start)
+ {
+@@ -1577,6 +1574,11 @@ update_insns ()
+ else if (CALL_P(insn))
+ {
+ ii.mark_call ();
++ if (inproepilogue)
++ {
++ returns.insert (infos.size () - 1);
++ inproepilogue = IN_CODE;
++ }
+ }
+ else
+ {
+
+From c11163ef6d4388e710fde92c1cc609ac06b0a5fc Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 30 May 2017 23:12:51 +0200
+Subject: [PATCH 154/303] @B fix single reg pop if stack frame gets removed
+
+---
+ gcc/bbb-opts.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index a187666945f0..a2c305c1f65c 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -1132,6 +1132,15 @@ replace_reg (rtx x, unsigned regno, rtx newreg, int offset)
+ void
+ insn_info::a5_to_a7 (rtx a7)
+ {
++ if (proepi == IN_EPILOGUE && src_mem_reg && get_src_mem_regno () == FRAME_POINTER_REGNUM)
++ {
++ rtx set = single_set (insn);
++ if (set)
++ {
++ SET_SRC(set) = gen_rtx_MEM(mode, gen_rtx_POST_INC(SImode, a7));
++ return;
++ }
++ }
+ replace_reg (PATTERN (insn), FRAME_POINTER_REGNUM, a7, -4);
+ }
+
+
+From 1ebf051b5bd078fc19f105904090ffc1743752fc Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 1 Jun 2017 16:05:59 +0200
+Subject: [PATCH 155/303] @B improved scan to treat endless loops (.L1: jra L1)
+ and similar constructs
+
+---
+ gcc/bbb-opts.c | 60 +++++++++++++++++++++++++++++++++++-----------------------
+ 1 file changed, 36 insertions(+), 24 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index a2c305c1f65c..26ca56bbb84d 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -483,12 +483,18 @@ class insn_info
+ }
+
+ inline void
+- mark_use (int regno)
++ mark_myuse (int regno)
+ {
+ myuse |= 1 << regno;
+ use |= 1 << regno;
+ }
+
++ inline void
++ mark_use (int regno)
++ {
++ use |= 1 << regno;
++ }
++
+ inline void
+ mark_def (int regno)
+ {
+@@ -722,11 +728,11 @@ insn_info::scan ()
+ if (sz <= 64)
+ {
+ mark_hard (0);
+- mark_use (0);
++ mark_myuse (0);
+ if (sz > 32)
+ {
+ mark_hard (1);
+- mark_use (1);
++ mark_myuse (1);
+ }
+ }
+ }
+@@ -739,7 +745,7 @@ insn_info::scan ()
+
+ if (GET_CODE (op = XEXP (link, 0)) == USE && REG_P(reg = XEXP (op, 0)))
+ for (unsigned r = REGNO(reg); r <= END_REGNO (reg); ++r)
+- mark_use (r);
++ mark_myuse (r);
+ }
+ /* mark scratch registers. */
+ mark_def (0);
+@@ -759,13 +765,13 @@ insn_info::scan_rtx (rtx x)
+ if (REG_P(x))
+ {
+ for (int n = REG_NREGS(x), r = REGNO(x); n > 0; --n, ++r)
+- mark_use (r);
++ mark_myuse (r);
+ return;
+ }
+
+ if (x == cc0_rtx)
+ {
+- mark_use (FIRST_PSEUDO_REGISTER);
++ mark_myuse (FIRST_PSEUDO_REGISTER);
+ return;
+ }
+
+@@ -1019,7 +1025,7 @@ typedef std::multimap<unsigned, unsigned>::iterator j2l_iterator;
+ static std::map<rtx_insn *, insn_info *> insn2info;
+ typedef std::map<rtx_insn *, insn_info *>::iterator i2i_iterator;
+
+-static std::set<unsigned> returns;
++static std::set<unsigned> scan_starts;
+ typedef std::set<unsigned>::iterator su_iterator;
+
+ static insn_info * info0;
+@@ -1137,7 +1143,7 @@ insn_info::a5_to_a7 (rtx a7)
+ rtx set = single_set (insn);
+ if (set)
+ {
+- SET_SRC(set) = gen_rtx_MEM(mode, gen_rtx_POST_INC(SImode, a7));
++ SET_SRC(set) = gen_rtx_MEM (mode, gen_rtx_POST_INC(SImode, a7));
+ return;
+ }
+ }
+@@ -1221,7 +1227,7 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol)
+ SET_INSN_DELETED(insn);
+ insn = emit_insn_after (pattern, insn);
+
+- mark_use (regno);
++ mark_myuse (regno);
+
+ insn2info.insert (std::make_pair (insn, this));
+ }
+@@ -1235,7 +1241,7 @@ clear (void)
+ jump2label.clear ();
+ insn2info.clear ();
+ infos.clear ();
+- returns.clear ();
++ scan_starts.clear ();
+ }
+
+ /*
+@@ -1348,9 +1354,7 @@ static void
+ update_insn_infos (void)
+ {
+ /* add all return (jump outs) and start analysis there. */
+- std::set<unsigned> todo;
+- for (su_iterator i = returns.begin (); i != returns.end (); ++i)
+- todo.insert (*i);
++ std::set<unsigned> & todo = scan_starts;
+
+ if (todo.begin () == todo.end ())
+ todo.insert (infos.size () - 1);
+@@ -1417,12 +1421,13 @@ update_insn_infos (void)
+ insn_info use (insn);
+ use.scan ();
+
++ /* do not mark a node as visited, if it's in epilogue and not yet visited. */
+ if (CALL_P(insn) || JUMP_P(insn))
+ {
+- if (pos != start)
++ if (pos != start && ii.in_proepi ())
+ {
+- su_iterator k = returns.find (pos);
+- if (k != returns.end ())
++ su_iterator k = scan_starts.find (pos);
++ if (k != scan_starts.end ())
+ {
+ pp.clear_visited ();
+ break;
+@@ -1510,7 +1515,7 @@ update_insns ()
+ {
+ if (inproepilogue || ANY_RETURN_P(PATTERN (insn)))
+ {
+- returns.insert (infos.size () - 1);
++ scan_starts.insert (infos.size () - 1);
+ inproepilogue = IN_CODE;
+ rtx set = single_set (insn);
+ if (ANY_RETURN_P(PATTERN (insn))
+@@ -1579,13 +1584,15 @@ update_insns ()
+ ii.mark_label ();
+ jump_table = 0;
+ ii.set_proepi (inproepilogue = IN_CODE);
++ if (infos.size () > 1)
++ scan_starts.insert (infos.size () - 1);
+ }
+ else if (CALL_P(insn))
+ {
+ ii.mark_call ();
+ if (inproepilogue)
+ {
+- returns.insert (infos.size () - 1);
++ scan_starts.insert (infos.size () - 1);
+ inproepilogue = IN_CODE;
+ }
+ }
+@@ -1614,7 +1621,7 @@ update_insns ()
+ inproepilogue = IN_EPILOGUE;
+ }
+ }
+-
++ scan_starts.insert (infos.size () - 1);
+ update_insn2index ();
+ update_insn_infos ();
+
+@@ -1666,14 +1673,17 @@ find_start (std::set<unsigned> & found, unsigned start, unsigned rename_regno)
+ break;
+
+ /* do not run over RETURNS */
+- rtx_insn * before = infos[startm1].get_insn ();
+- if (JUMP_P(before) && ANY_RETURN_P(PATTERN (before)))
++ insn_info & jj = infos[start];
++ insn_info & bb = infos[startm1];
++ if (jj.in_proepi () == IN_CODE && bb.in_proepi () >= IN_EPILOGUE)
+ break;
++// rtx_insn * before = infos[startm1].get_insn ();
++// if (JUMP_P(before) && ANY_RETURN_P(PATTERN (before)))
++// break;
+
+ start = startm1;
+
+ /* found the definition without use. */
+- insn_info & jj = infos[start];
+ if (jj.is_def (rename_regno) && !jj.is_use (rename_regno))
+ break;
+
+@@ -3351,6 +3361,8 @@ opt_absolute (void)
+ else
+ log ("(b) modifying %d absolute addresses using %s\n", found.size (), reg_names[regno]);
+
++ unsigned current_use = ii.get_use ();
++
+ for (std::vector<unsigned>::iterator k = found.begin (); k != found.end (); ++k)
+ {
+ insn_info & kk = infos[*k];
+@@ -3373,7 +3385,7 @@ opt_absolute (void)
+ lea = gen_rtx_SET(gen_raw_REG (SImode, regno), gen_rtx_CONST_INT (SImode, base));
+ rtx_insn * insn = emit_insn_before (lea, ii.get_insn ());
+ insn_info nn (insn);
+- nn.set_use (ii.get_use ());
++ nn.set_use (current_use);
+ nn.scan ();
+ nn.fledder (lea);
+ nn.mark_def (regno);
+@@ -3496,7 +3508,7 @@ namespace
+ done = 0, update_insns ();
+
+ if (do_absolute && opt_absolute ())
+- done = 0;
++ done = 0, update_insns ();
+
+ if (do_bb_reg_rename)
+ {
+
+From 21a94abb83e5a01f912dbc66951cc32797d05ed3 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 2 Jun 2017 20:11:26 +0200
+Subject: [PATCH 156/303] @B fix opt_reg_rename: backward search for defs was
+ off by one @N startet to add register tracking
+
+---
+ gcc/bbb-opts.c | 236 ++++++++++++++++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 193 insertions(+), 43 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 26ca56bbb84d..9014295f8b43 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -167,16 +167,31 @@ class insn_info
+ int dst_autoinc;
+ int src_autoinc;
+
++ // values for all variables - if used
++ rtx * values;
++
+ public:
+ insn_info (rtx_insn * i = 0, enum proepis p = IN_CODE) :
+ insn (i), myuse (0), hard (0), use (0), def (0), proepi (p), stack (false), label (false), jump (false), call (
+ false), compare (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus (false), src_op (
+ (rtx_code) 0), src_ee (false), src_const (false), mode (VOIDmode), dst_reg (0), dst_mem_reg (0), dst_symbol (
+ 0), src_reg (0), src_mem_reg (0), src_symbol (0), dst_mem_addr (0), src_intval (0), src_mem_addr (0), visited (
+- false), sp_offset (0), dst_autoinc (0), src_autoinc (0)
++ false), sp_offset (0), dst_autoinc (0), src_autoinc (0), values (0)
+ {
+ }
+
++ void
++ set_values (rtx * v);
++
++ bool
++ merge_values (rtx * v);
++
++ bool
++ equal_values (rtx * v) const;
++
++ rtx
++ get_value_for (unsigned regno) const;
++
+ inline ptrdiff_t
+ operator < (insn_info const & o) const
+ {
+@@ -421,7 +436,7 @@ class insn_info
+ return stack;
+ }
+
+- inline int
++ inline enum proepis
+ in_proepi () const
+ {
+ return proepi;
+@@ -716,6 +731,56 @@ class insn_info
+ a5_to_a7 (rtx a7);
+ };
+
++void
++insn_info::set_values (rtx * v)
++{
++ if (!values)
++ values = new rtx[16];
++ memcpy (values, v, 16 * sizeof(rtx));
++}
++
++static const rtx INVALID = (rtx) -1;
++
++bool
++insn_info::merge_values (rtx * v)
++{
++ bool r = false;
++ if (!values)
++ r = true, set_values (v);
++ else
++ for (int i = 0; i < 16; ++i)
++ if (!values[i])
++ r = true, values[i] = v[i];
++ else if (values[i] != INVALID && v[i] && v[i] != INVALID && !rtx_equal_p (values[i], v[i]))
++ r = true, values[i] = INVALID;
++ return r;
++}
++
++bool
++insn_info::equal_values (rtx * v) const
++{
++ if (!values)
++ return false;
++ for (int i = 0; i < 16; ++i)
++ if (values[i] && !v[i])
++ return false;
++ else if (v[i] && !values[i])
++ return false;
++ else if (values[i] == INVALID && v[i] != INVALID)
++ return false;
++ else if (!rtx_equal_p (values[i], v[i]))
++ return false;
++ return true;
++}
++
++rtx
++insn_info::get_value_for (unsigned regno) const
++{
++ if (!values || regno > 15)
++ return 0;
++ return values[regno];
++}
++
+ void
+ insn_info::scan ()
+ {
+@@ -1365,13 +1430,18 @@ update_insn_infos (void)
+ todo.erase (todo.begin ());
+ insn_info ii = infos[start];
+
++ enum proepis proepi = ii.in_proepi ();
++
+ for (int pos = start; pos >= 0; --pos)
+ {
+ insn_info & pp = infos[pos];
+ rtx_insn * insn = pp.get_insn ();
+- /* can be NULL as used in opt_shrink_stack_frame(). */
+- if (!insn)
+- continue;
++
++ // do not run into previous epilogue
++ if (pp.in_proepi () >= IN_EPILOGUE && !proepi)
++ break;
++
++ proepi = pp.in_proepi ();
+
+ /* no new information -> break. */
+ if (pos != start && pp.is_visited () && !JUMP_P(insn) && pp.contains (ii))
+@@ -1677,16 +1747,12 @@ find_start (std::set<unsigned> & found, unsigned start, unsigned rename_regno)
+ insn_info & bb = infos[startm1];
+ if (jj.in_proepi () == IN_CODE && bb.in_proepi () >= IN_EPILOGUE)
+ break;
+-// rtx_insn * before = infos[startm1].get_insn ();
+-// if (JUMP_P(before) && ANY_RETURN_P(PATTERN (before)))
+-// break;
+-
+- start = startm1;
+
+ /* found the definition without use. */
+ if (jj.is_def (rename_regno) && !jj.is_use (rename_regno))
+ break;
+
++ start = startm1;
+ }
+ return start;
+ }
+@@ -2531,39 +2597,6 @@ opt_const_cmp_to_sub (void)
+ return change_count;
+ }
+
+-/*
+- * Some optimizations (e.g. propagate_moves) might result into an unused assignment behind the loop.
+- * delete those insns.
+- */
+-static unsigned
+-opt_elim_dead_assign (void)
+-{
+- unsigned change_count = 0;
+- for (int index = infos.size () - 1; index >= 0; --index)
+- {
+- rtx_insn * insn = infos[index].get_insn ();
+- if (!NONJUMP_INSN_P(insn))
+- continue;
+-
+- rtx set = single_set (insn);
+- if (!set)
+- continue;
+-
+- rtx src = SET_SRC(set);
+- rtx dst = SET_DEST(set);
+- if (!REG_P(dst) || !REG_P(src))
+- continue;
+-
+- if (is_reg_dead (REGNO(dst), index))
+- {
+- log ("(e) %d: elim_dead_assign to %s\n", index, reg_names[REGNO(dst)]);
+- SET_INSN_DELETED(insn);
+- ++change_count;
+- }
+- }
+- return change_count;
+-}
+-
+ /*
+ * rare and only little gain - but :-)
+ lea (-1,a0),a1
+@@ -3233,6 +3266,123 @@ opt_shrink_stack_frame (void)
+ return changed;
+ }
+
++/* Update the insn_infos to 'know' the value for each register. */
++static unsigned
++track_regs ()
++{
++ // reset visited flags
++ for (unsigned index = 0; index < infos.size (); ++index)
++ {
++ insn_info & ii = infos[index];
++ ii.clear_visited ();
++ ii.set_sp_offset (0);
++ }
++
++ // add entry point
++ std::set<unsigned> todo;
++ todo.insert (0);
++
++ while (todo.begin () != todo.end ())
++ {
++ unsigned startpos = *todo.begin ();
++ todo.erase (todo.begin ());
++
++ rtx * values = new rtx[16]; // track dx/ax
++ memset (values, 0, 16 * sizeof(rtx));
++
++ for (unsigned index = startpos; index < infos.size (); ++index)
++ {
++ insn_info & ii = infos[index];
++
++ // already visited?
++ if (ii.is_visited () && ii.equal_values (values))
++ break;
++
++ // mark current insn_info and set sp_offset
++ ii.mark_visited ();
++
++ ii.merge_values (values);
++
++ // add all referred labels
++ if (ii.is_jump ())
++ {
++ for (j2l_iterator i = jump2label.find (index), k = i; i != jump2label.end () && i->first == k->first; ++i)
++ {
++ todo.insert (i->second);
++ insn_info & jj = infos[i->second];
++ if (jj.merge_values (values))
++ ii.clear_visited ();
++ }
++ continue;
++ }
++
++ // track register values for now
++ int regno = ii.get_dst_regno ();
++ if (regno < 0)
++ {
++ // TODO: track if dst_mem is volatile
++ continue;
++ }
++
++ rtx set = single_set (ii.get_insn ());
++ if (!set)
++ continue;
++
++ rtx src = SET_SRC(set);
++
++ // TODO: check for volatile sources
++ values[regno] = src;
++
++ for (int i = regno + 1; i < END_REGNO (ii.get_dst_reg ()); ++i)
++ values[regno] = INVALID;
++ }
++ }
++ return 0;
++}
++
++/*
++ * Some optimizations (e.g. propagate_moves) might result into an unused assignment behind the loop.
++ * delete those insns.
++ */
++static unsigned
++opt_elim_dead_assign (void)
++{
++ track_regs ();
++
++ unsigned change_count = 0;
++ for (int index = infos.size () - 1; index >= 0; --index)
++ {
++ insn_info & ii = infos[index];
++ if (!ii.get_dst_reg ())
++ continue;
++
++ rtx_insn * insn = ii.get_insn ();
++ rtx set = single_set (insn);
++ if (!set)
++
++ if (ii.get_src_reg () && is_reg_dead (ii.get_dst_regno (), index))
++ {
++ log ("(e) %d: eliminate dead assign to %s\n", index, reg_names[ii.get_dst_regno ()]);
++ SET_INSN_DELETED(insn);
++ ++change_count;
++ continue;
++ }
++
++ continue;
++
++ rtx cached_value = ii.get_value_for (ii.get_dst_regno ());
++ if (cached_value && cached_value != INVALID && rtx_equal_p (cached_value, SET_SRC(set)))
++ {
++ log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]);
++ SET_INSN_DELETED(insn);
++ ++change_count;
++ continue;
++
++ }
++ }
++ return change_count;
++}
++
+ /*
+ * Convert a series of move into absolute address into register based moves.
+ */
+
+From 98fb7816dc4ef9e568a068343dbcf331ccdca4d0 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sat, 3 Jun 2017 17:40:50 +0200
+Subject: [PATCH 157/303] @B fix opt_shrink_stack_frame: not all sp offsets
+ were patched
+
+---
+ gcc/bbb-opts.c | 120 +++++++++++++++++++++++++++++++++++----------------------
+ 1 file changed, 74 insertions(+), 46 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 9014295f8b43..00ac220456b2 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -146,6 +146,7 @@ class insn_info
+ bool src_plus;
+ rtx_code src_op;
+ bool src_ee;
++ bool src_2nd;
+ bool src_const;
+
+ machine_mode mode;
+@@ -174,9 +175,9 @@ class insn_info
+ insn_info (rtx_insn * i = 0, enum proepis p = IN_CODE) :
+ insn (i), myuse (0), hard (0), use (0), def (0), proepi (p), stack (false), label (false), jump (false), call (
+ false), compare (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus (false), src_op (
+- (rtx_code) 0), src_ee (false), src_const (false), mode (VOIDmode), dst_reg (0), dst_mem_reg (0), dst_symbol (
+- 0), src_reg (0), src_mem_reg (0), src_symbol (0), dst_mem_addr (0), src_intval (0), src_mem_addr (0), visited (
+- false), sp_offset (0), dst_autoinc (0), src_autoinc (0), values (0)
++ (rtx_code) 0), src_ee (false), src_2nd (false), src_const (false), mode (VOIDmode), dst_reg (0), dst_mem_reg (
++ 0), dst_symbol (0), src_reg (0), src_mem_reg (0), src_symbol (0), dst_mem_addr (0), src_intval (0), src_mem_addr (
++ 0), visited (false), sp_offset (0), dst_autoinc (0), src_autoinc (0), values (0)
+ {
+ }
+
+@@ -240,6 +241,12 @@ class insn_info
+ return src_mem;
+ }
+
++ inline bool
++ is_src_mem_2nd () const
++ {
++ return src_2nd && src_mem;
++ }
++
+ inline bool
+ has_dst_memreg () const
+ {
+@@ -408,6 +415,9 @@ class insn_info
+ void
+ fledder (rtx set);
+
++ void
++ fledder_src_mem (rtx src);
++
+ /* update usage. */
+ void
+ update (insn_info & o)
+@@ -872,6 +882,51 @@ insn_info::scan_rtx (rtx x)
+ }
+ }
+
++void
++insn_info::fledder_src_mem (rtx src)
++{
++ src_mem = true;
++ rtx mem = XEXP(src, 0);
++
++ if (GET_CODE(mem) == POST_INC)
++ src_autoinc = 1, mem = XEXP(mem, 0);
++ else if (GET_CODE(mem) == PRE_DEC)
++ src_autoinc = -1, mem = XEXP(mem, 0);
++
++ if (REG_P(mem))
++ src_mem_reg = mem;
++ else if (GET_CODE(mem) == CONST_INT)
++ src_mem_addr = INTVAL(mem);
++ else if (GET_CODE(mem) == SYMBOL_REF)
++ src_symbol = mem;
++ else if (GET_CODE(mem) == PLUS)
++ {
++ src_plus = true;
++ rtx reg = XEXP(mem, 0);
++ rtx konst = XEXP(mem, 1);
++ if (REG_P(reg) && GET_CODE(konst) == CONST_INT)
++ {
++ src_mem_reg = reg;
++ src_const = true;
++ src_mem_addr = INTVAL(konst);
++ }
++ }
++ else if (GET_CODE(mem) == CONST)
++ {
++ mem = XEXP(mem, 0);
++ if (GET_CODE(mem) == PLUS)
++ {
++ rtx sym = XEXP(mem, 0);
++ if (GET_CODE(sym) == SYMBOL_REF)
++ {
++ src_plus = true;
++ src_symbol = sym;
++ src_mem_addr = INTVAL(XEXP(mem, 1));
++ }
++ }
++ }
++}
++
+ /* read the set and grab infos */
+ void
+ insn_info::fledder (rtx set)
+@@ -959,7 +1014,15 @@ insn_info::fledder (rtx set)
+ if (GET_CODE(operand) == CONST_INT || GET_CODE(operand) == CONST_WIDE_INT)
+ src_const = true, src_intval = INTVAL(operand);
+ else if (REG_P(operand))
+- alt_src_reg = operand;
++ {
++ alt_src_reg = operand;
++ }
++ else if (MEM_P(operand))
++ {
++ // it' something like reg = op(reg, mem(...))
++ src_2nd = true;
++ fledder_src_mem (operand);
++ }
+ }
+ src = XEXP(src, 0);
+ }
+@@ -970,46 +1033,7 @@ insn_info::fledder (rtx set)
+ }
+ else if (MEM_P(src))
+ {
+- src_mem = true;
+- rtx mem = XEXP(src, 0);
+-
+- if (GET_CODE(mem) == POST_INC)
+- src_autoinc = 1, mem = XEXP(mem, 0);
+- else if (GET_CODE(mem) == PRE_DEC)
+- src_autoinc = -1, mem = XEXP(mem, 0);
+-
+- if (REG_P(mem))
+- src_mem_reg = mem;
+- else if (GET_CODE(mem) == CONST_INT)
+- src_mem_addr = INTVAL(mem);
+- else if (GET_CODE(mem) == SYMBOL_REF)
+- src_symbol = mem;
+- else if (GET_CODE(mem) == PLUS)
+- {
+- src_plus = true;
+- rtx reg = XEXP(mem, 0);
+- rtx konst = XEXP(mem, 1);
+- if (REG_P(reg) && GET_CODE(konst) == CONST_INT)
+- {
+- src_mem_reg = reg;
+- src_const = true;
+- src_mem_addr = INTVAL(konst);
+- }
+- }
+- else if (GET_CODE(mem) == CONST)
+- {
+- mem = XEXP(mem, 0);
+- if (GET_CODE(mem) == PLUS)
+- {
+- rtx sym = XEXP(mem, 0);
+- if (GET_CODE(sym) == SYMBOL_REF)
+- {
+- src_plus = true;
+- src_symbol = sym;
+- src_mem_addr = INTVAL(XEXP(mem, 1));
+- }
+- }
+- }
++ fledder_src_mem (src);
+ }
+ else if (GET_CODE(src) == CONST_INT)
+ {
+@@ -3173,7 +3197,11 @@ opt_shrink_stack_frame (void)
+ rtx src = XEXP(pattern, 1);
+ rtx plus = XEXP(src, 0);
+ if (ii.get_src_op ())
+- plus = XEXP(plus, 0);
++ {
++ plus = XEXP(src, 1);
++ if (MEM_P(plus))
++ plus = XEXP(plus, 0);
++ }
+ XEXP(plus, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(plus, 1)), ii.get_src_mem_addr () - adjust);
+ }
+
+@@ -3333,7 +3361,7 @@ track_regs ()
+ // TODO: check for volatile sources
+ values[regno] = src;
+
+- for (int i = regno + 1; i < END_REGNO (ii.get_dst_reg ()); ++i)
++ for (unsigned i = regno + 1; i < END_REGNO (ii.get_dst_reg ()); ++i)
+ values[regno] = INVALID;
+ }
+ }
+
+From 3d0257b6111e90dab6f704f81bb6c0a5adc3191f Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Sat, 3 Jun 2017 19:01:51 +0100
+Subject: [PATCH 158/303] @V bump datestamp
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index b5d1e40685b6..54bc2fee3dce 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170529-215512
++20170603-190132
+
+From a64448fa986d1e9e89b7214926213844749cb330 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 4 Jun 2017 10:54:35 +0200
+Subject: [PATCH 159/303] @B removed bogus (and not yet used) code
+
+---
+ gcc/bbb-opts.c | 86 ----------------------------------------------------------
+ 1 file changed, 86 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 00ac220456b2..11c3891025e9 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -3294,80 +3294,6 @@ opt_shrink_stack_frame (void)
+ return changed;
+ }
+
+-/* Update the insn_infos to 'know' the value for each register. */
+-static unsigned
+-track_regs ()
+-{
+- // reset visited flags
+- for (unsigned index = 0; index < infos.size (); ++index)
+- {
+- insn_info & ii = infos[index];
+- ii.clear_visited ();
+- ii.set_sp_offset (0);
+- }
+-
+- // add entry point
+- std::set<unsigned> todo;
+- todo.insert (0);
+-
+- while (todo.begin () != todo.end ())
+- {
+- unsigned startpos = *todo.begin ();
+- todo.erase (todo.begin ());
+-
+- rtx * values = new rtx[16]; // track dx/ax
+- memset (values, 0, 16 * sizeof(rtx));
+-
+- for (unsigned index = startpos; index < infos.size (); ++index)
+- {
+- insn_info & ii = infos[index];
+-
+- // already visited?
+- if (ii.is_visited () && ii.equal_values (values))
+- break;
+-
+- // mark current insn_info and set sp_offset
+- ii.mark_visited ();
+-
+- ii.merge_values (values);
+-
+- // add all referred labels
+- if (ii.is_jump ())
+- {
+- for (j2l_iterator i = jump2label.find (index), k = i; i != jump2label.end () && i->first == k->first; ++i)
+- {
+- todo.insert (i->second);
+- insn_info & jj = infos[i->second];
+- if (jj.merge_values (values))
+- ii.clear_visited ();
+- }
+- continue;
+- }
+-
+- // track register values for now
+- int regno = ii.get_dst_regno ();
+- if (regno < 0)
+- {
+- // TODO: track if dst_mem is volatile
+- continue;
+- }
+-
+- rtx set = single_set (ii.get_insn ());
+- if (!set)
+- continue;
+-
+- rtx src = SET_SRC(set);
+-
+- // TODO: check for volatile sources
+- values[regno] = src;
+-
+- for (unsigned i = regno + 1; i < END_REGNO (ii.get_dst_reg ()); ++i)
+- values[regno] = INVALID;
+- }
+- }
+- return 0;
+-}
+-
+ /*
+ * Some optimizations (e.g. propagate_moves) might result into an unused assignment behind the loop.
+ * delete those insns.
+@@ -3375,8 +3301,6 @@ track_regs ()
+ static unsigned
+ opt_elim_dead_assign (void)
+ {
+- track_regs ();
+-
+ unsigned change_count = 0;
+ for (int index = infos.size () - 1; index >= 0; --index)
+ {
+@@ -3397,16 +3321,6 @@ opt_elim_dead_assign (void)
+ }
+
+ continue;
+-
+- rtx cached_value = ii.get_value_for (ii.get_dst_regno ());
+- if (cached_value && cached_value != INVALID && rtx_equal_p (cached_value, SET_SRC(set)))
+- {
+- log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]);
+- SET_INSN_DELETED(insn);
+- ++change_count;
+- continue;
+-
+- }
+ }
+ return change_count;
+ }
+
+From 5a66c60ad7bba806de2640310c4e3e4941245aa2 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 5 Jun 2017 00:00:30 +0200
+Subject: [PATCH 160/303] @B fix reg use/def marking in ASM_SPEC, @B rewrote SP
+ offset patcher, @N added variable tracking and (e)liminate redundat load
+
+---
+ gcc/bbb-opts.c | 296 ++++++++++++++++++++++++++++++++++++++++++++++++---------
+ 1 file changed, 251 insertions(+), 45 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 11c3891025e9..e9a8df7d1c01 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -181,6 +181,9 @@ class insn_info
+ {
+ }
+
++ rtx *
++ get_values ();
++
+ void
+ set_values (rtx * v);
+
+@@ -741,12 +744,23 @@ class insn_info
+ a5_to_a7 (rtx a7);
+ };
+
++rtx *
++insn_info::get_values ()
++{
++ if (values)
++ return values;
++
++ values = (rtx *) xmalloc (FIRST_PSEUDO_REGISTER * sizeof(rtx));
++ memset (values, 0xff, FIRST_PSEUDO_REGISTER * sizeof(rtx));
++ return values;
++}
++
+ void
+ insn_info::set_values (rtx * v)
+ {
+ if (!values)
+- values = new rtx[16];
+- memcpy (values, v, 16 * sizeof(rtx));
++ values = (rtx *) xmalloc (FIRST_PSEUDO_REGISTER * sizeof(rtx));
++ memcpy (values, v, FIRST_PSEUDO_REGISTER * sizeof(rtx));
+ }
+
+ static const rtx INVALID = (rtx) -1;
+@@ -758,7 +772,7 @@ insn_info::merge_values (rtx * v)
+ if (!values)
+ r = true, set_values (v);
+ else
+- for (int i = 0; i < 16; ++i)
++ for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+ if (!values[i])
+ r = true, values[i] = v[i];
+ else if (values[i] != INVALID && v[i] && v[i] != INVALID && !rtx_equal_p (values[i], v[i]))
+@@ -771,7 +785,7 @@ insn_info::equal_values (rtx * v) const
+ {
+ if (!values)
+ return false;
+- for (int i = 0; i < 16; ++i)
++ for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+ if (values[i] && !v[i])
+ return false;
+ else if (v[i] && !values[i])
+@@ -857,6 +871,7 @@ insn_info::scan_rtx (rtx x)
+ {
+ unsigned u = use;
+ unsigned mu = myuse;
++ use = myuse = 0;
+ scan_rtx (SET_DEST(x));
+ if (REG_P(SET_DEST(x)))
+ {
+@@ -867,7 +882,7 @@ insn_info::scan_rtx (rtx x)
+ scan_rtx (SET_SRC(x));
+ int code = GET_CODE(SET_SRC(x));
+ if (code == ASM_OPERANDS)
+- use = hard |= def | use;
++ hard |= def | use;
+ return;
+ }
+
+@@ -878,7 +893,15 @@ insn_info::scan_rtx (rtx x)
+ scan_rtx (XEXP(x, i));
+ else if (fmt[i] == 'E')
+ for (int j = XVECLEN (x, i) - 1; j >= 0; j--)
+- scan_rtx (XVECEXP(x, i, j));
++ {
++ unsigned u = use;
++ unsigned mu = myuse;
++ unsigned d = def;
++ scan_rtx (XVECEXP(x, i, j));
++ use |= u;
++ myuse |= myuse;
++ def |= d;
++ }
+ }
+ }
+
+@@ -2775,6 +2798,33 @@ track_sp ()
+ return 0;
+ }
+
++/* recursive function to patch stack pointer offsets. */
++void
++patch_sp (rtx x, int adjust, int spoffset)
++{
++ int code = GET_CODE(x);
++ if (code == PLUS)
++ {
++ rtx a = XEXP(x, 0);
++ rtx b = XEXP(x, 1);
++ if (REG_P(a) && REGNO(a) == STACK_POINTER_REGNUM && GET_CODE(b) == CONST_INT)
++ {
++ if (INTVAL(b) > -spoffset)
++ XEXP(x, 1) = gen_rtx_CONST_INT (GET_MODE(b), INTVAL(b) - adjust);
++ return;
++ }
++ }
++ const char *fmt = GET_RTX_FORMAT(code);
++ for (int i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
++ {
++ if (fmt[i] == 'e')
++ patch_sp (XEXP(x, i), adjust, spoffset);
++ else if (fmt[i] == 'E')
++ for (int j = XVECLEN (x, i) - 1; j >= 0; j--)
++ patch_sp (XVECEXP(x, i, j), adjust, spoffset);
++ }
++}
++
+ /**
+ * 1. scan for all used registers.
+ * 2. scan the stack from for omittable push/pop
+@@ -3179,37 +3229,8 @@ opt_shrink_stack_frame (void)
+ continue;
+
+ rtx pattern = single_set (ii.get_insn ());
+- if (ii.is_compare ())
+- pattern = XEXP(pattern, 1);
+-
+- // lea n(sp),ax
+- if (ii.get_src_reg () && ii.get_src_regno () == STACK_POINTER_REGNUM && ii.get_src_op () == PLUS)
+- {
+- // touch only if above pushed parameters
+- if (ii.get_src_intval () > -ii.get_sp_offset ())
+- {
+- rtx src = XEXP(pattern, 1);
+- XEXP(src, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(src, 1)), ii.get_src_intval () - adjust);
+- }
+- }
+- else if (ii.is_src_mem () && ii.is_src_mem_plus () && ii.get_src_mem_regno () == STACK_POINTER_REGNUM)
+- {
+- rtx src = XEXP(pattern, 1);
+- rtx plus = XEXP(src, 0);
+- if (ii.get_src_op ())
+- {
+- plus = XEXP(src, 1);
+- if (MEM_P(plus))
+- plus = XEXP(plus, 0);
+- }
+- XEXP(plus, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(plus, 1)), ii.get_src_mem_addr () - adjust);
+- }
+-
+- if (ii.is_dst_mem () && ii.is_dst_mem_plus () && ii.get_dst_mem_regno () == STACK_POINTER_REGNUM)
+- {
+- rtx plus = XEXP(XEXP(pattern, 0), 0);
+- XEXP(plus, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(plus, 1)), ii.get_dst_intval () - adjust);
+- }
++ if (pattern)
++ patch_sp (pattern, adjust, ii.get_sp_offset ());
+ }
+ }
+
+@@ -3294,6 +3315,168 @@ opt_shrink_stack_frame (void)
+ return changed;
+ }
+
++/* Update the insn_infos to 'know' the value for each register. */
++static unsigned
++track_regs ()
++{
++ // reset visited flags
++ for (unsigned index = 0; index < infos.size (); ++index)
++ {
++ insn_info & ii = infos[index];
++ ii.clear_visited ();
++ ii.set_sp_offset (0);
++ }
++
++ rtx * values = (rtx *) xmalloc (FIRST_PSEUDO_REGISTER * sizeof(rtx)); // track register values
++
++ // add entry point
++ std::set<unsigned> todo;
++ todo.insert (0);
++
++ while (todo.begin () != todo.end ())
++ {
++ unsigned startpos = *todo.begin ();
++ todo.erase (todo.begin ());
++
++ memset (values, 0xff, FIRST_PSEUDO_REGISTER * sizeof(rtx));
++
++ // track register aliases: know which register refers to this slot
++ // if a register changes, invalidate each referrer
++ std::multimap<unsigned, unsigned> r2r;
++ for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
++ if (values[i] && values[i] != INVALID && REG_P(values[i]))
++ r2r.insert (std::make_pair (REGNO(values[i]), i));
++
++ for (unsigned index = startpos; index < infos.size (); ++index)
++ {
++ insn_info & ii = infos[index];
++
++ // already visited?
++ if (ii.is_visited () && ii.equal_values (values))
++ break;
++
++ // mark current insn_info and set sp_offset
++ ii.mark_visited ();
++
++ // do not optimize over labels
++ if (ii.is_label ())
++ {
++ memset (values, 0xff, FIRST_PSEUDO_REGISTER * sizeof(rtx));
++ continue;
++ }
++
++ ii.merge_values (values);
++
++ if (ii.is_compare ())
++ continue;
++
++ unsigned def = ii.get_def ();
++ if (def)
++ {
++ for (int i = 0; i < 16; ++i)
++ if ((1 << i) & def)
++ {
++ values[i] = 0;
++ // invalidate all referring registers
++ for (std::multimap<unsigned, unsigned>::iterator j = r2r.find (i), k = j;
++ j != r2r.end () && j->first == k->first;)
++ {
++ values[j->second] = INVALID;
++ r2r.erase (j++);
++ }
++ }
++ }
++
++ if (ii.is_call ())
++ continue;
++
++ // add all referred labels
++ if (ii.is_jump ())
++ {
++ for (j2l_iterator i = jump2label.find (index), k = i; i != jump2label.end () && i->first == k->first; ++i)
++ {
++ todo.insert (i->second);
++ insn_info & jj = infos[i->second];
++ if (jj.merge_values (values))
++ ii.clear_visited ();
++ }
++ continue;
++ }
++
++ rtx set = single_set (ii.get_insn ());
++ if (!set)
++ continue;
++
++ rtx src, dest;
++ if (ii.get_src_autoinc ())
++ {
++ int regno = ii.get_src_mem_regno ();
++ values[regno] = INVALID;
++ for (std::multimap<unsigned, unsigned>::iterator j = r2r.find (regno), k = j;
++ j != r2r.end () && j->first == k->first;)
++ {
++ values[j->second] = INVALID;
++ r2r.erase (j++);
++ }
++ }
++
++ if (ii.get_src_op () || ii.get_src_autoinc () || ((ii.get_myuse () - 1) & ii.get_myuse ()))
++ src = INVALID;
++ else
++ {
++ src = SET_SRC(set);
++ if (ii.is_src_mem () && src->volatil)
++ src = INVALID;
++ }
++
++ if (ii.get_dst_autoinc ())
++ {
++ int regno = ii.get_dst_mem_regno ();
++ values[regno] = INVALID;
++ for (std::multimap<unsigned, unsigned>::iterator j = r2r.find (regno), k = j;
++ j != r2r.end () && j->first == k->first;)
++ {
++ values[j->second] = INVALID;
++ r2r.erase (j++);
++ }
++ }
++
++ if (src == INVALID || ii.get_src_op () || ii.get_dst_autoinc ())
++ dest = INVALID;
++ else
++ dest = SET_DEST(set);
++
++ // track register values for now
++ int dregno = ii.get_dst_regno ();
++ int sregno = ii.get_src_regno ();
++
++ // track r2r
++ if (dregno >= 0 && sregno >= 0)
++ {
++ r2r.insert (std::make_pair (dregno, sregno));
++ r2r.insert (std::make_pair (sregno, dregno));
++ }
++
++ if (sregno >= 0)
++ {
++ values[sregno] = dest;
++ for (unsigned i = sregno + 1; i < END_REGNO (ii.get_src_reg ()); ++i)
++ values[i] = INVALID;
++ }
++
++ if (dregno >= 0)
++ {
++ // TODO: check for volatile sources
++ values[dregno] = src;
++ for (unsigned i = dregno + 1; i < END_REGNO (ii.get_dst_reg ()); ++i)
++ values[i] = INVALID;
++
++ }
++ }
++ }
++ return 0;
++}
++
+ /*
+ * Some optimizations (e.g. propagate_moves) might result into an unused assignment behind the loop.
+ * delete those insns.
+@@ -3301,11 +3484,13 @@ opt_shrink_stack_frame (void)
+ static unsigned
+ opt_elim_dead_assign (void)
+ {
++ track_regs ();
++
+ unsigned change_count = 0;
+ for (int index = infos.size () - 1; index >= 0; --index)
+ {
+ insn_info & ii = infos[index];
+- if (!ii.get_dst_reg ())
++ if (!ii.get_dst_reg () || ii.is_compare ())
+ continue;
+
+ rtx_insn * insn = ii.get_insn ();
+@@ -3319,8 +3504,23 @@ opt_elim_dead_assign (void)
+ ++change_count;
+ continue;
+ }
++ if (ii.get_src_op () == 0)
++ {
++ rtx cached_value = ii.get_value_for (ii.get_dst_regno ());
++ rtx cached_value2 = 0;
++ if (cached_value && cached_value != INVALID && REG_P(cached_value) && REGNO(cached_value) < 16)
++ cached_value2 = ii.get_value_for (REGNO(cached_value));
++ if (cached_value && cached_value != INVALID
++ && (rtx_equal_p (cached_value, SET_SRC(set))
++ || (cached_value2 && cached_value2 != INVALID && rtx_equal_p (cached_value2, SET_SRC(set)))))
++ {
++ log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]);
++ SET_INSN_DELETED(insn);
++ ++change_count;
++ continue;
+
+- continue;
++ }
++ }
+ }
+ return change_count;
+ }
+@@ -3360,8 +3560,8 @@ opt_absolute (void)
+
+ std::vector<unsigned> found;
+ found.push_back (i);
+- unsigned base = ii.get_dst_addr ();
+- unsigned max = base;
++ int base = ii.get_dst_addr ();
++ int max = base;
+ unsigned j = i + 1;
+ for (; j < infos.size (); ++j)
+ {
+@@ -3393,7 +3593,7 @@ opt_absolute (void)
+
+ if (j_dst)
+ {
+- unsigned addr = jj.get_dst_addr ();
++ int addr = jj.get_dst_addr ();
+ if (addr < base)
+ {
+ if (max - addr <= 0x7ffe)
+@@ -3413,7 +3613,7 @@ opt_absolute (void)
+ }
+ if (j_src)
+ {
+- unsigned addr = jj.get_src_mem_addr ();
++ int addr = jj.get_src_mem_addr ();
+ if (addr < base)
+ {
+ if (max - addr <= 0x7ffe)
+@@ -3439,8 +3639,14 @@ opt_absolute (void)
+ for (std::vector<unsigned>::iterator k = found.begin (); k != found.end ();)
+ {
+ insn_info & kk = infos[*k];
+- if (kk.get_dst_addr () - base > 0x7ffc)
+- found.erase (k);
++ bool k_dst = kk.is_dst_mem () && (kk.has_dst_addr () || kk.get_dst_symbol ()) && !kk.has_dst_memreg ()
++ && kk.get_dst_symbol () == with_symbol;
++ bool k_src = kk.is_src_mem () && (kk.has_src_addr () || kk.get_src_symbol ()) && !kk.has_src_memreg ()
++ && kk.get_src_symbol () == with_symbol;
++ if (k_dst && kk.get_dst_addr () - base > 0x7ffc)
++ found.erase (k++);
++ else if (k_src && kk.get_src_mem_addr () - base > 0x7ffc)
++ found.erase (k++);
+ else
+ ++k;
+ }
+
+From 09bb1d02257cbc120bb9f2fa8d4b49999662f328 Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Mon, 5 Jun 2017 09:10:12 +0100
+Subject: [PATCH 161/303] @V bump DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 54bc2fee3dce..cb00f5c9a36e 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170603-190132
++20170605-091011
+
+From 9be210ab91c70ab5776d8e01fb4c63e8b7695a0f Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 6 Jun 2017 16:56:04 +0200
+Subject: [PATCH 162/303] @I improve the algorithm to find redundant register
+ loads
+
+---
+ gcc/bbb-opts.c | 280 +++++++++++++++++++++++++++++++--------------------------
+ 1 file changed, 153 insertions(+), 127 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index e9a8df7d1c01..6fc53c674a4d 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -116,6 +116,76 @@ enum proepis
+ IN_CODE, IN_PROLOGUE, IN_EPILOGUE, IN_EPILOGUE_PARALLEL_POP
+ };
+
++class track_var
++{
++ rtx * values;
++ unsigned * versions;
++
++public:
++ track_var (track_var const * o = 0) :
++ values ((rtx *) xcalloc (FIRST_PSEUDO_REGISTER, sizeof(rtx))), versions (
++ (unsigned *) xcalloc (FIRST_PSEUDO_REGISTER, sizeof(unsigned)))
++ {
++ if (o)
++ assign (o);
++ }
++
++ rtx *
++ get_values () const
++ {
++ return values;
++ }
++
++ void
++ set_version (unsigned regno, unsigned ver)
++ {
++ if (regno < FIRST_PSEUDO_REGISTER)
++ versions[regno] = ver;
++ }
++
++ void
++ assign (track_var const * o) const
++ {
++ memcpy (values, o->values, FIRST_PSEUDO_REGISTER * sizeof(rtx));
++ memcpy (versions, o->versions, FIRST_PSEUDO_REGISTER * sizeof(unsigned));
++ }
++
++ /* only keep common values in both sides. */
++ void
++ merge (track_var * o)
++ {
++ for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
++ {
++ if (values[i] && o->values[i] && rtx_equal_p (values[i], o->values[i]))
++ {
++ int code = GET_CODE(values[i]);
++ if (code != CONST_INT && code != CONST_FIXED && code != CONST_DOUBLE && versions[i] != o->versions[i])
++ values[i] = o->values[i] = 0;
++ }
++ else
++ values[i] = o->values[i] = 0;
++ }
++ }
++
++ /* true if a merge would not change anything. */
++ bool
++ contains (track_var const * o) const
++ {
++ for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
++ {
++ if (values[i] && o->values[i] && rtx_equal_p (values[i], o->values[i]))
++ {
++ int code = GET_CODE(values[i]);
++ if (code != CONST_INT && code != CONST_FIXED && code != CONST_DOUBLE && versions[i] != o->versions[i])
++ return false;
++ }
++ else if (values[i])
++ return false;
++ }
++ return true;
++ }
++};
++
+ /* Information for each insn to detect alive registers. Enough for m68k.
+ * Why a class? Maybe extend it for general usage.
+ *
+@@ -125,7 +195,7 @@ class insn_info
+ {
+ rtx_insn * insn; // the insn
+
+- // usage flags
++// usage flags
+ unsigned myuse; // bit set if registers are used in this statement
+ unsigned hard; // bit set if registers can't be renamed
+ unsigned use; // bit set if registers are used in program flow
+@@ -135,7 +205,7 @@ class insn_info
+
+ bool stack; // part of stack frame insns
+
+- // stuff to analyze insns
++// stuff to analyze insns
+ bool label;
+ bool jump;
+ bool call;
+@@ -168,8 +238,8 @@ class insn_info
+ int dst_autoinc;
+ int src_autoinc;
+
+- // values for all variables - if used
+- rtx * values;
++// values for all variables - if used
++ track_var * track;
+
+ public:
+ insn_info (rtx_insn * i = 0, enum proepis p = IN_CODE) :
+@@ -177,24 +247,12 @@ class insn_info
+ false), compare (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus (false), src_op (
+ (rtx_code) 0), src_ee (false), src_2nd (false), src_const (false), mode (VOIDmode), dst_reg (0), dst_mem_reg (
+ 0), dst_symbol (0), src_reg (0), src_mem_reg (0), src_symbol (0), dst_mem_addr (0), src_intval (0), src_mem_addr (
+- 0), visited (false), sp_offset (0), dst_autoinc (0), src_autoinc (0), values (0)
++ 0), visited (false), sp_offset (0), dst_autoinc (0), src_autoinc (0), track (0)
+ {
+ }
+
+- rtx *
+- get_values ();
+-
+- void
+- set_values (rtx * v);
+-
+- bool
+- merge_values (rtx * v);
+-
+- bool
+- equal_values (rtx * v) const;
+-
+- rtx
+- get_value_for (unsigned regno) const;
++ track_var *
++ get_track_var ();
+
+ inline ptrdiff_t
+ operator < (insn_info const & o) const
+@@ -744,65 +802,12 @@ class insn_info
+ a5_to_a7 (rtx a7);
+ };
+
+-rtx *
+-insn_info::get_values ()
++track_var *
++insn_info::get_track_var ()
+ {
+- if (values)
+- return values;
+-
+- values = (rtx *) xmalloc (FIRST_PSEUDO_REGISTER * sizeof(rtx));
+- memset (values, 0xff, FIRST_PSEUDO_REGISTER * sizeof(rtx));
+- return values;
+-}
+-
+-void
+-insn_info::set_values (rtx * v)
+-{
+- if (!values)
+- values = (rtx *) xmalloc (FIRST_PSEUDO_REGISTER * sizeof(rtx));
+- memcpy (values, v, FIRST_PSEUDO_REGISTER * sizeof(rtx));
+-}
+-
+-static const rtx INVALID = (rtx) -1;
+-
+-bool
+-insn_info::merge_values (rtx * v)
+-{
+- bool r = false;
+- if (!values)
+- r = true, set_values (v);
+- else
+- for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+- if (!values[i])
+- r = true, values[i] = v[i];
+- else if (values[i] != INVALID && v[i] && v[i] != INVALID && !rtx_equal_p (values[i], v[i]))
+- r = true, values[i] = INVALID;
+- return r;
+-}
+-
+-bool
+-insn_info::equal_values (rtx * v) const
+-{
+- if (!values)
+- return false;
+- for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+- if (values[i] && !v[i])
+- return false;
+- else if (v[i] && !values[i])
+- return false;
+- else if (values[i] == INVALID && v[i] != INVALID)
+- return false;
+- else if (!rtx_equal_p (values[i], v[i]))
+- return false;
+- return true;
+-}
+-
+-rtx
+-insn_info::get_value_for (unsigned regno) const
+-{
+- if (!values || regno > 15)
+- return 0;
+- return values[regno];
++ if (!track)
++ track = new track_var ();
++ return track;
+ }
+
+ void
+@@ -899,7 +904,7 @@ insn_info::scan_rtx (rtx x)
+ unsigned d = def;
+ scan_rtx (XVECEXP(x, i, j));
+ use |= u;
+- myuse |= myuse;
++ myuse |= mu;
+ def |= d;
+ }
+ }
+@@ -1185,12 +1190,12 @@ insn_info::get_index () const
+ return pos;
+ }
+
+- // realloc happened...
++// realloc happened...
+ for (unsigned i = 0; i < infos.size (); ++i)
+ if (infos[i].get_insn () == this->insn)
+ return i;
+
+- // whoops!?
++// whoops!?
+ return 0;
+ }
+
+@@ -1201,7 +1206,7 @@ insn_info::plus_to_move (rtx_insn * newinsn)
+ src_op = (rtx_code) 0;
+ src_reg = XEXP(PATTERN (newinsn), 1);
+ insn2info.insert (std::make_pair (insn, this));
+- // usage flags did not change
++// usage flags did not change
+ }
+
+ void
+@@ -1214,7 +1219,7 @@ insn_info::swap_adds (rtx_insn * newinsn, insn_info & ii)
+ insn2info.insert (std::make_pair (insn, this));
+ insn2info.insert (std::make_pair (ii.insn, &ii));
+
+- // usage flags did not change
++// usage flags did not change
+ }
+
+ static
+@@ -1363,7 +1368,7 @@ clear (void)
+ static bool
+ is_reg_dead (unsigned regno, unsigned _pos)
+ {
+- // skip labels.
++// skip labels.
+ for (unsigned pos = _pos + 1; pos < infos.size (); ++pos)
+ {
+ insn_info & ii0 = infos[pos];
+@@ -2719,7 +2724,7 @@ opt_merge_add (void)
+ static unsigned
+ track_sp ()
+ {
+- // reset visited flags
++// reset visited flags
+ for (unsigned index = 0; index < infos.size (); ++index)
+ {
+ insn_info & ii = infos[index];
+@@ -2727,7 +2732,7 @@ track_sp ()
+ ii.set_sp_offset (0);
+ }
+
+- // add entry point
++// add entry point
+ std::set<unsigned> todo;
+ todo.insert (0);
+
+@@ -3319,7 +3324,7 @@ opt_shrink_stack_frame (void)
+ static unsigned
+ track_regs ()
+ {
+- // reset visited flags
++// reset visited flags
+ for (unsigned index = 0; index < infos.size (); ++index)
+ {
+ insn_info & ii = infos[index];
+@@ -3327,45 +3332,59 @@ track_regs ()
+ ii.set_sp_offset (0);
+ }
+
+- rtx * values = (rtx *) xmalloc (FIRST_PSEUDO_REGISTER * sizeof(rtx)); // track register values
++ update_label2jump ();
+
+- // add entry point
+- std::set<unsigned> todo;
+- todo.insert (0);
++// add entry point
++ std::map<unsigned, track_var *> todo;
++ todo.insert (std::make_pair (0, new track_var ()));
+
+ while (todo.begin () != todo.end ())
+ {
+- unsigned startpos = *todo.begin ();
++ unsigned startpos = todo.begin ()->first;
++ track_var * const track = todo.begin ()->second;
+ todo.erase (todo.begin ());
+
+- memset (values, 0xff, FIRST_PSEUDO_REGISTER * sizeof(rtx));
+-
++ rtx * values = track->get_values ();
+ // track register aliases: know which register refers to this slot
+ // if a register changes, invalidate each referrer
+ std::multimap<unsigned, unsigned> r2r;
+ for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+- if (values[i] && values[i] != INVALID && REG_P(values[i]))
++ if (values[i] && REG_P(values[i]))
+ r2r.insert (std::make_pair (REGNO(values[i]), i));
+
++ unsigned version = startpos;
++
+ for (unsigned index = startpos; index < infos.size (); ++index)
+ {
+ insn_info & ii = infos[index];
+
+ // already visited?
+- if (ii.is_visited () && ii.equal_values (values))
++ if (ii.is_visited () && ii.get_track_var ()->contains (track))
+ break;
+
+- // mark current insn_info and set sp_offset
+- ii.mark_visited ();
+-
+- // do not optimize over labels
++ // only keep common values at labels
+ if (ii.is_label ())
+ {
+- memset (values, 0xff, FIRST_PSEUDO_REGISTER * sizeof(rtx));
++ version = index;
++ if (ii.is_visited ())
++ {
++ ii.get_track_var ()->merge (track);
++ r2r.clear ();
++ for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
++ if (values[i] && REG_P(values[i]))
++ r2r.insert (std::make_pair (REGNO(values[i]), i));
++ }
++ else
++ {
++ ii.get_track_var ()->assign (track);
++ ii.mark_visited ();
++ }
+ continue;
+ }
+
+- ii.merge_values (values);
++ // mark current insn_info and set sp_offset
++ ii.mark_visited ();
++ ii.get_track_var ()->assign (track);
+
+ if (ii.is_compare ())
+ continue;
+@@ -3381,7 +3400,7 @@ track_regs ()
+ for (std::multimap<unsigned, unsigned>::iterator j = r2r.find (i), k = j;
+ j != r2r.end () && j->first == k->first;)
+ {
+- values[j->second] = INVALID;
++ values[j->second] = 0;
+ r2r.erase (j++);
+ }
+ }
+@@ -3390,20 +3409,27 @@ track_regs ()
+ if (ii.is_call ())
+ continue;
+
++ rtx set = single_set (ii.get_insn ());
++
+ // add all referred labels
+ if (ii.is_jump ())
+ {
++ if (ANY_RETURN_P(ii.get_insn ()))
++ break;
++
+ for (j2l_iterator i = jump2label.find (index), k = i; i != jump2label.end () && i->first == k->first; ++i)
++ todo.insert (std::make_pair (i->second, new track_var (track)));
++
++ if (set && GET_CODE(SET_SRC(set)) == IF_THEN_ELSE)
+ {
+- todo.insert (i->second);
+- insn_info & jj = infos[i->second];
+- if (jj.merge_values (values))
+- ii.clear_visited ();
++ version = index;
++ continue;
+ }
+- continue;
++
++ // unconditional jump
++ break;
+ }
+
+- rtx set = single_set (ii.get_insn ());
+ if (!set)
+ continue;
+
+@@ -3411,38 +3437,38 @@ track_regs ()
+ if (ii.get_src_autoinc ())
+ {
+ int regno = ii.get_src_mem_regno ();
+- values[regno] = INVALID;
++ values[regno] = 0;
+ for (std::multimap<unsigned, unsigned>::iterator j = r2r.find (regno), k = j;
+ j != r2r.end () && j->first == k->first;)
+ {
+- values[j->second] = INVALID;
++ values[j->second] = 0;
+ r2r.erase (j++);
+ }
+ }
+
+ if (ii.get_src_op () || ii.get_src_autoinc () || ((ii.get_myuse () - 1) & ii.get_myuse ()))
+- src = INVALID;
++ src = 0;
+ else
+ {
+ src = SET_SRC(set);
+ if (ii.is_src_mem () && src->volatil)
+- src = INVALID;
++ src = 0;
+ }
+
+ if (ii.get_dst_autoinc ())
+ {
+ int regno = ii.get_dst_mem_regno ();
+- values[regno] = INVALID;
++ values[regno] = 0;
+ for (std::multimap<unsigned, unsigned>::iterator j = r2r.find (regno), k = j;
+ j != r2r.end () && j->first == k->first;)
+ {
+- values[j->second] = INVALID;
++ values[j->second] = 0;
+ r2r.erase (j++);
+ }
+ }
+
+- if (src == INVALID || ii.get_src_op () || ii.get_dst_autoinc ())
+- dest = INVALID;
++ if (src == 0 || ii.get_src_op () || ii.get_dst_autoinc ())
++ dest = 0;
+ else
+ dest = SET_DEST(set);
+
+@@ -3460,19 +3486,20 @@ track_regs ()
+ if (sregno >= 0)
+ {
+ values[sregno] = dest;
++ track->set_version (sregno, version);
+ for (unsigned i = sregno + 1; i < END_REGNO (ii.get_src_reg ()); ++i)
+- values[i] = INVALID;
++ values[i] = 0;
+ }
+
+ if (dregno >= 0)
+ {
+- // TODO: check for volatile sources
+ values[dregno] = src;
++ track->set_version (dregno, version);
+ for (unsigned i = dregno + 1; i < END_REGNO (ii.get_dst_reg ()); ++i)
+- values[i] = INVALID;
+-
++ values[i] = 0;
+ }
+ }
++ delete track;
+ }
+ return 0;
+ }
+@@ -3504,21 +3531,20 @@ opt_elim_dead_assign (void)
+ ++change_count;
+ continue;
+ }
+- if (ii.get_src_op () == 0)
++ if (ii.get_src_op () == 0 && ii.get_dst_reg ())
+ {
+- rtx cached_value = ii.get_value_for (ii.get_dst_regno ());
++ rtx cached_value = ii.get_track_var ()->get_values ()[ii.get_dst_regno ()];
+ rtx cached_value2 = 0;
+- if (cached_value && cached_value != INVALID && REG_P(cached_value) && REGNO(cached_value) < 16)
+- cached_value2 = ii.get_value_for (REGNO(cached_value));
+- if (cached_value && cached_value != INVALID
++ if (cached_value && REG_P(cached_value) && REGNO(cached_value) < FIRST_PSEUDO_REGISTER)
++ cached_value2 = ii.get_track_var ()->get_values ()[REGNO(cached_value)];
++ if (cached_value
+ && (rtx_equal_p (cached_value, SET_SRC(set))
+- || (cached_value2 && cached_value2 != INVALID && rtx_equal_p (cached_value2, SET_SRC(set)))))
++ || (cached_value2 && rtx_equal_p (cached_value2, SET_SRC(set)))))
+ {
+ log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]);
+ SET_INSN_DELETED(insn);
+ ++change_count;
+ continue;
+-
+ }
+ }
+ }
+
+From eaecabb03f08d5c95aea084f47753a8249c9170a Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 7 Jun 2017 13:03:52 +0200
+Subject: [PATCH 163/303] @B enable eliminate dead assignments again, @B fix sp
+ shrinking, @B disable stack frame removal for eh handlers
+
+---
+ gcc/bbb-opts.c | 71 +++++++++++++++++++++++++++++++++++-----------------------
+ 1 file changed, 43 insertions(+), 28 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 6fc53c674a4d..4f14d0799ac4 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -1505,21 +1505,29 @@ update_insn_infos (void)
+ if (LABEL_P(insn))
+ {
+ /* work on all jumps referring to that label. */
+- for (l2j_iterator i = label2jump.find (insn->u2.insn_uid), k = i;
+- i != label2jump.end () && i->first == k->first; ++i)
+- {
+- i2i_iterator j = insn2info.find (i->second);
+- if (j != insn2info.end ())
+- {
+- unsigned index = j->second->get_index ();
+- insn_info & jj = infos[index];
+- if (!jj.is_visited () || !jj.contains (ii))
+- {
+- jj.updateWith (ii);
+- todo.insert (index);
+- }
+- }
+- }
++ l2j_iterator i = label2jump.find (insn->u2.insn_uid);
++
++ /* no jump to here -> mark all registers as hard regs.
++ * This label is maybe used in an exception handler.
++ * Marking as hard also avoids stack frame removal.
++ */
++ if (i == label2jump.end ())
++ infos[pos + 1].make_hard ();
++ else
++ for (l2j_iterator k = i; i != label2jump.end () && i->first == k->first; ++i)
++ {
++ i2i_iterator j = insn2info.find (i->second);
++ if (j != insn2info.end ())
++ {
++ unsigned index = j->second->get_index ();
++ insn_info & jj = infos[index];
++ if (!jj.is_visited () || !jj.contains (ii))
++ {
++ jj.updateWith (ii);
++ todo.insert (index);
++ }
++ }
++ }
+
+ if (pos == start)
+ pp.mark_visited ();
+@@ -3128,7 +3136,7 @@ opt_shrink_stack_frame (void)
+ }
+ else
+ {
+- rtx parallel = gen_rtx_PARALLEL(VOIDmode, rtvec_alloc (regs.size () + add1));
++ rtx parallel = gen_rtx_PARALLEL(VOIDmode, rtvec_alloc (regs.size () + add1 + clobbers.size ()));
+ rtx plus;
+
+ int x = 0;
+@@ -3137,7 +3145,7 @@ opt_shrink_stack_frame (void)
+
+ unsigned l = 0;
+ /* no add if a5 is used with pop */
+- if (!usea5 || i < prologueend)
++ if (add1)
+ {
+ plus = gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, i < prologueend ? -x : x));
+ XVECEXP(parallel, 0, l) = gen_rtx_SET(a7, plus);
+@@ -3180,12 +3188,18 @@ opt_shrink_stack_frame (void)
+ }
+ }
+
+- for (unsigned k = 0; k < clobbers.size (); ++k)
++ for (unsigned k = 0; k < clobbers.size (); ++k, ++l)
+ {
+ rtx clobber = clobbers[k];
+- XVECEXP(parallel, 0, l++) = clobber;
++ XVECEXP(parallel, 0, l) = clobber;
+ }
+- emit_insn_after (parallel, insn);
++
++ rtx_insn * neu;
++ if (i < prologueend)
++ neu = emit_insn_after (parallel, insn);
++ else
++ neu = emit_insn_before (parallel, insn);
++ ii.set_insn (neu);
+ }
+ SET_INSN_DELETED(insn);
+ changed = 1;
+@@ -3517,20 +3531,21 @@ opt_elim_dead_assign (void)
+ for (int index = infos.size () - 1; index >= 0; --index)
+ {
+ insn_info & ii = infos[index];
+- if (!ii.get_dst_reg () || ii.is_compare ())
++ if (ii.in_proepi () || !ii.get_dst_reg () || ii.is_compare ())
+ continue;
+
+ rtx_insn * insn = ii.get_insn ();
+ rtx set = single_set (insn);
+ if (!set)
++ continue;
+
+- if (ii.get_src_reg () && is_reg_dead (ii.get_dst_regno (), index))
+- {
+- log ("(e) %d: eliminate dead assign to %s\n", index, reg_names[ii.get_dst_regno ()]);
+- SET_INSN_DELETED(insn);
+- ++change_count;
+- continue;
+- }
++ if (ii.get_dst_reg () && is_reg_dead (ii.get_dst_regno (), index))
++ {
++ log ("(e) %d: eliminate dead assign to %s\n", index, reg_names[ii.get_dst_regno ()]);
++ SET_INSN_DELETED(insn);
++ ++change_count;
++ continue;
++ }
+ if (ii.get_src_op () == 0 && ii.get_dst_reg ())
+ {
+ rtx cached_value = ii.get_track_var ()->get_values ()[ii.get_dst_regno ()];
+
+From 9dad7c865fe3b09382759e1b35f29d577948f88d Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 8 Jun 2017 15:05:24 +0200
+Subject: [PATCH 164/303] @B added a workaround for shared CLOBBERS (argh\!),
+ @B mark sp as used in epilogue to avoid elimination of sp corrections, @B
+ defs with mode size < 4 are now always an use too
+
+---
+ gcc/bbb-opts.c | 25 +++++++++++++++++++++----
+ 1 file changed, 21 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 4f14d0799ac4..9825b55a1ea7 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -1121,7 +1121,15 @@ temp_reg_rename (std::vector<std::pair<rtx *, rtx> > & loc, rtx x, unsigned oldr
+ }
+ else if (fmt[i] == 'E')
+ for (int j = XVECLEN (x, i) - 1; j >= 0; j--)
+- temp_reg_rename (loc, XVECEXP(x, i, j), oldregno, newregno);
++ {
++ rtx z = XVECEXP(x, i, j);
++ if (GET_CODE(z) == CLOBBER)
++ {
++ /* workaround for shared clobbers. */
++ XVECEXP(x, i, j) = z = gen_rtx_CLOBBER(GET_MODE(z), XEXP(z, 0));
++ }
++ temp_reg_rename (loc, z, oldregno, newregno);
++ }
+ }
+ }
+
+@@ -1484,6 +1492,10 @@ update_insn_infos (void)
+
+ enum proepis proepi = ii.in_proepi ();
+
++ // mark sp reg as used.
++ if (proepi >= IN_EPILOGUE)
++ ii.mark_use (STACK_POINTER_REGNUM), infos[start].mark_use (STACK_POINTER_REGNUM);
++
+ for (int pos = start; pos >= 0; --pos)
+ {
+ insn_info & pp = infos[pos];
+@@ -1578,6 +1590,10 @@ update_insn_infos (void)
+ NOTICE_UPDATE_CC(PATTERN (insn), insn);
+ if (cc_status.value1 || cc_status.value2)
+ use.mark_def (FIRST_PSEUDO_REGISTER);
++
++ // also check mode size if < 4, it's also a def.
++ if (ii.get_dst_reg () && GET_MODE_SIZE(ii.get_mode()) < 4)
++ use.mark_def (ii.get_dst_regno ());
+ }
+
+ /* mark not renameable in prologue/epilogue. */
+@@ -3696,7 +3712,8 @@ opt_absolute (void)
+ {
+ unsigned regno = bit2regno (freemask);
+ if (with_symbol)
+- log ("(b) modifying %d symbol addresses using %s\n", found.size (), reg_names[regno]);
++ log ("(b) modifying %d symbol addresses for %s using %s\n", found.size (),
++ with_symbol->u.block_sym.fld[0].rt_str, reg_names[regno]);
+ else
+ log ("(b) modifying %d absolute addresses using %s\n", found.size (), reg_names[regno]);
+
+@@ -3843,10 +3860,10 @@ namespace
+ if (do_merge_add && opt_merge_add ())
+ done = 0;
+
+- if (do_elim_dead_assign && opt_elim_dead_assign ())
++ if (do_absolute && opt_absolute ())
+ done = 0, update_insns ();
+
+- if (do_absolute && opt_absolute ())
++ if (do_elim_dead_assign && opt_elim_dead_assign ())
+ done = 0, update_insns ();
+
+ if (do_bb_reg_rename)
+
+From b6bf8403f6febb237c2ae37474c97bb989c40f60 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 9 Jun 2017 13:41:35 +0200
+Subject: [PATCH 165/303] @B mark all returns and jumps (in calls) sp using, @B
+ keep volatile flag in absolute_base conversion
+
+---
+ gcc/bbb-opts.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 9825b55a1ea7..c8d29013f981 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -1291,7 +1291,7 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol)
+ rtx set = single_set (get_insn ());
+ rtx src = SET_SRC(set);
+ rtx dst = SET_DEST(set);
+-
++ bool vola = src->volatil;
+ rtx pattern;
+ rtx reg = gen_raw_REG (SImode, regno);
+
+@@ -1348,6 +1348,7 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol)
+ }
+
+ pattern = gen_rtx_SET(dst, src);
++ src->volatil = vola;
+
+ SET_INSN_DELETED(insn);
+ insn = emit_insn_after (pattern, insn);
+@@ -1661,6 +1662,9 @@ update_insns ()
+ {
+ if (inproepilogue || ANY_RETURN_P(PATTERN (insn)))
+ {
++ if (ANY_RETURN_P(PATTERN (insn)))
++ ii.set_proepi(IN_EPILOGUE);
++
+ scan_starts.insert (infos.size () - 1);
+ inproepilogue = IN_CODE;
+ rtx set = single_set (insn);
+@@ -1696,6 +1700,7 @@ update_insns ()
+ {
+ rtx label = XEXP(ref, 0);
+ label2jump.insert (std::make_pair (label->u2.insn_uid, insn));
++ ii.set_proepi(IN_EPILOGUE);
+ }
+ }
+ }
+@@ -1735,6 +1740,8 @@ update_insns ()
+ }
+ else if (CALL_P(insn))
+ {
++ if (insn->jump)
++ ii.set_proepi(IN_EPILOGUE);
+ ii.mark_call ();
+ if (inproepilogue)
+ {
+
+From d8619150fdaca31cc31de96fe94f4e4bd212fe76 Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Fri, 9 Jun 2017 15:00:32 +0100
+Subject: [PATCH 166/303] @V bump DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index cb00f5c9a36e..ba919c60d861 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170605-091011
++20170609-145423
+
+From d485949ff4cc8d323dbf9b4810fd379ccbe98cfc Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 11 Jun 2017 13:04:22 +0200
+Subject: [PATCH 167/303] @R excluded fpgnulib.c from libgcc
+
+---
+ libgcc/config.host | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/libgcc/config.host b/libgcc/config.host
+index f456ff689ad9..1478faa2b027 100644
+--- libgcc/config.host
++++ libgcc/config.host
+@@ -817,8 +817,7 @@ m32rle-*-linux*)
+ tmake_file="$tmake_file m32r/t-linux t-fdpbit"
+ ;;
+ m68k-*-amiga*)
+- tmake_file="$tmake_file
+-# m68k/t-floatlib"
++# tmake_file="$tmake_file m68k/t-floatlib"
+ ;;
+ m68k-*-elf* | fido-*-elf)
+ tmake_file="$tmake_file m68k/t-floatlib"
+
+From 4ed9bba08719add41aec99292e4dc315699f6111 Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Sun, 11 Jun 2017 12:06:59 +0100
+Subject: [PATCH 168/303] @V bump DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index ba919c60d861..e7d6b1e3aa50 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170609-145423
++20170611-120626
+
+From cd1e07319580d7ea753d8202fe8a03aec19a9b3b Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 11 Jun 2017 22:40:39 +0200
+Subject: [PATCH 169/303] @B fix linking add -lstubs again
+
+---
+ gcc/config/m68k/m68kamigaos.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h
+index 8a25f8cbfdfb..50859a4c283f 100644
+--- gcc/config/m68k/m68kamigaos.h
++++ gcc/config/m68k/m68kamigaos.h
+@@ -487,7 +487,7 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ #define LIBGCC_IXEMUL_SPEC ""
+ #define LIBGCC_LIBNIX_SPEC "-lnix -fl libnix " \
+ "%{mcrt=*:-l%*} " \
+- "%{!mcrt=*:-lnix20}"
++ "%{!mcrt=*:-lnix20} -lstubs"
+ #define LIBGCC_CLIB2_SPEC "-lc"
+ #define LIBGCC_SPEC "-lgcc " \
+ "%{noixemul:%(libgcc_libnix)} " \
+
+From 40fa6300271e5cd3d886f54d5696c6e748ecdc52 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 11 Jun 2017 22:41:23 +0200
+Subject: [PATCH 170/303] @B lock a4 if baserel, @B better invalidation in
+ register tracking
+
+---
+ gcc/bbb-opts.c | 168 +++++++++++++++++++++++++++++++++------------------------
+ 1 file changed, 98 insertions(+), 70 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index c8d29013f981..9a0a3ac80e43 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -1126,7 +1126,7 @@ temp_reg_rename (std::vector<std::pair<rtx *, rtx> > & loc, rtx x, unsigned oldr
+ if (GET_CODE(z) == CLOBBER)
+ {
+ /* workaround for shared clobbers. */
+- XVECEXP(x, i, j) = z = gen_rtx_CLOBBER(GET_MODE(z), XEXP(z, 0));
++ XVECEXP(x, i, j) = z = gen_rtx_CLOBBER (GET_MODE(z), XEXP(z, 0));
+ }
+ temp_reg_rename (loc, z, oldregno, newregno);
+ }
+@@ -1268,7 +1268,7 @@ insn_info::a5_to_a7 (rtx a7)
+ rtx set = single_set (insn);
+ if (set)
+ {
+- SET_SRC(set) = gen_rtx_MEM (mode, gen_rtx_POST_INC(SImode, a7));
++ SET_SRC(set) = gen_rtx_MEM (mode, gen_rtx_POST_INC (SImode, a7));
+ return;
+ }
+ }
+@@ -1304,7 +1304,7 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol)
+ if (base == addr)
+ dst = gen_rtx_MEM (mode, reg);
+ else
+- dst = gen_rtx_MEM (mode, gen_rtx_PLUS(SImode, reg, gen_rtx_CONST_INT (SImode, offset)));
++ dst = gen_rtx_MEM (mode, gen_rtx_PLUS (SImode, reg, gen_rtx_CONST_INT (SImode, offset)));
+
+ dst_mem_reg = reg;
+ dst_mem = true;
+@@ -1322,13 +1322,13 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol)
+ if (base == addr)
+ src = gen_rtx_MEM (mode, reg);
+ else
+- src = gen_rtx_MEM (mode, gen_rtx_PLUS(SImode, reg, gen_rtx_CONST_INT (SImode, offset)));
++ src = gen_rtx_MEM (mode, gen_rtx_PLUS (SImode, reg, gen_rtx_CONST_INT (SImode, offset)));
+
+ /* some operation to the same value as dst. eg. eor #5,symbol+8 -> eor #5,8(ax) */
+ if (src_op)
+ {
+ if (src_ee)
+- src = gen_rtx_fmt_ee(src_op, mode, src, gen_rtx_CONST_INT (mode, src_intval));
++ src = gen_rtx_fmt_ee (src_op, mode, src, gen_rtx_CONST_INT (mode, src_intval));
+ else
+ {
+ if (src_op == SIGN_EXTEND)
+@@ -1336,7 +1336,7 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol)
+ PUT_MODE_RAW(src, mode == SImode ? HImode : mode == HImode ? QImode : SImode);
+ src->call = 1;
+ }
+- src = gen_rtx_fmt_e(src_op, mode, src);
++ src = gen_rtx_fmt_e (src_op, mode, src);
+ }
+ }
+
+@@ -1347,7 +1347,7 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol)
+ }
+ }
+
+- pattern = gen_rtx_SET(dst, src);
++ pattern = gen_rtx_SET (dst, src);
+ src->volatil = vola;
+
+ SET_INSN_DELETED(insn);
+@@ -1485,6 +1485,8 @@ update_insn_infos (void)
+ if (todo.begin () == todo.end ())
+ todo.insert (infos.size () - 1);
+
++ bool locka4 = flag_pic >= 3;
++
+ while (!todo.empty ())
+ {
+ int start = *todo.begin ();
+@@ -1563,6 +1565,8 @@ update_insn_infos (void)
+ rtx pattern = PATTERN (insn);
+ insn_info use (insn);
+ use.scan ();
++ if (locka4 && (use.get_myuse () & (1 << PIC_REG)))
++ use.mark_hard (PIC_REG);
+
+ /* do not mark a node as visited, if it's in epilogue and not yet visited. */
+ if (CALL_P(insn) || JUMP_P(insn))
+@@ -1663,7 +1667,7 @@ update_insns ()
+ if (inproepilogue || ANY_RETURN_P(PATTERN (insn)))
+ {
+ if (ANY_RETURN_P(PATTERN (insn)))
+- ii.set_proepi(IN_EPILOGUE);
++ ii.set_proepi (IN_EPILOGUE);
+
+ scan_starts.insert (infos.size () - 1);
+ inproepilogue = IN_CODE;
+@@ -1700,7 +1704,7 @@ update_insns ()
+ {
+ rtx label = XEXP(ref, 0);
+ label2jump.insert (std::make_pair (label->u2.insn_uid, insn));
+- ii.set_proepi(IN_EPILOGUE);
++ ii.set_proepi (IN_EPILOGUE);
+ }
+ }
+ }
+@@ -1741,7 +1745,7 @@ update_insns ()
+ else if (CALL_P(insn))
+ {
+ if (insn->jump)
+- ii.set_proepi(IN_EPILOGUE);
++ ii.set_proepi (IN_EPILOGUE);
+ ii.mark_call ();
+ if (inproepilogue)
+ {
+@@ -1860,6 +1864,11 @@ opt_reg_rename (void)
+
+ /* get the mask for free registers. */
+ unsigned mask = ii.get_free_mask ();
++
++ /* do not use a4 if compiling baserel */
++ if (flag_pic >= 3)
++ mask &= ~(1 << PIC_REG);
++
+ if (!mask)
+ continue;
+
+@@ -2300,8 +2309,8 @@ opt_propagate_moves ()
+
+ for (unsigned k = 0; k < jump_out.size (); ++k)
+ {
+- rtx neu = gen_rtx_SET(
+- dstj, gen_rtx_PLUS(Pmode, dsti, gen_rtx_CONST_INT(Pmode, fixups[k])));
++ rtx neu = gen_rtx_SET (
++ dstj, gen_rtx_PLUS (Pmode, dsti, gen_rtx_CONST_INT (Pmode, fixups[k])));
+ emit_insn_after (neu, jump_out[k]);
+ }
+ }
+@@ -2377,7 +2386,7 @@ opt_strcpy ()
+ int num_clobbers_to_add = 0;
+ int insn_code_number;
+
+- rtx pattern = gen_rtx_SET(SET_DEST(single_set(reg2x)), SET_SRC(single_set (x2reg)));
++ rtx pattern = gen_rtx_SET (SET_DEST(single_set (reg2x)), SET_SRC(single_set (x2reg)));
+ rtx_insn * newinsn = make_insn_raw (pattern);
+ insn_code_number = recog (PATTERN (newinsn), newinsn, &num_clobbers_to_add);
+ if (insn_code_number >= 0 && check_asm_operands (PATTERN (newinsn)))
+@@ -2489,10 +2498,10 @@ opt_commute_add_move (void)
+ if (!REG_P(memreg) || REGNO(memreg) != REGNO(reg1src))
+ continue;
+
+- rtx pinc = gen_rtx_POST_INC(GET_MODE(dst), reg1dst);
++ rtx pinc = gen_rtx_POST_INC (GET_MODE(dst), reg1dst);
+ rtx newmem = replace_equiv_address_nv (dst, pinc);
+
+- rtx_insn * newinsn = make_insn_raw (gen_rtx_SET(reg1dst, reg1src));
++ rtx_insn * newinsn = make_insn_raw (gen_rtx_SET (reg1dst, reg1src));
+ if (recog (PATTERN (newinsn), newinsn, 0) < 0 || !check_asm_operands (PATTERN (newinsn)))
+ continue;
+
+@@ -2620,9 +2629,9 @@ opt_const_cmp_to_sub (void)
+ {
+ rtx copyreg = copy_reg (i1.get_dst_reg (), -1);
+ /* create the sub statement. */
+- rtx sub = gen_rtx_PLUS(i1.get_mode (), copyreg, gen_rtx_CONST_INT (i1.get_mode (), intval));
++ rtx sub = gen_rtx_PLUS (i1.get_mode (), copyreg, gen_rtx_CONST_INT (i1.get_mode (), intval));
+
+- rtx_insn * subinsn = make_insn_raw (gen_rtx_SET(copyreg, sub));
++ rtx_insn * subinsn = make_insn_raw (gen_rtx_SET (copyreg, sub));
+
+ int num_clobbers_to_add = 0;
+ int insn_code_number = recog (PATTERN (subinsn), subinsn, &num_clobbers_to_add);
+@@ -2639,8 +2648,8 @@ opt_const_cmp_to_sub (void)
+ subinsn = emit_insn_before (PATTERN (subinsn), i1.get_insn ());
+ i1.set_insn (subinsn);
+
+- rtx neu = gen_rtx_SET(cc0_rtx,
+- gen_rtx_COMPARE(i1.get_mode (), copyreg, gen_rtx_CONST_INT(i1.get_mode (), 0)));
++ rtx neu = gen_rtx_SET (cc0_rtx,
++ gen_rtx_COMPARE (i1.get_mode (), copyreg, gen_rtx_CONST_INT (i1.get_mode (), 0)));
+
+ emit_insn_before (neu, i2.get_insn ());
+
+@@ -2661,8 +2670,8 @@ opt_const_cmp_to_sub (void)
+ /* still a compare with 0 -> insert the sub. */
+ rtx copyreg = copy_reg (i1.get_dst_reg (), -1);
+ /* create the sub statement. */
+- rtx sub = gen_rtx_PLUS(i1.get_mode (), copyreg, c);
+- rtx set = gen_rtx_SET(copyreg, sub);
++ rtx sub = gen_rtx_PLUS (i1.get_mode (), copyreg, c);
++ rtx set = gen_rtx_SET (copyreg, sub);
+ emit_insn_before (set, pp.get_insn ());
+ }
+ else
+@@ -2734,7 +2743,7 @@ opt_merge_add (void)
+ rtx set = PATTERN (insn0);
+
+ // convert lea (-1,a0),a1 into move.l a0,a1
+- rtx_insn * newins0 = make_insn_raw (gen_rtx_SET(XEXP(set, 0), XEXP(XEXP(set, 1), 0)));
++ rtx_insn * newins0 = make_insn_raw (gen_rtx_SET (XEXP(set, 0), XEXP(XEXP(set, 1), 0)));
+ add_insn_after (newins0, insn0, 0);
+ SET_INSN_DELETED(insn0);
+ // update infos accordingly
+@@ -3142,24 +3151,24 @@ opt_shrink_stack_frame (void)
+ if (i < prologueend)
+ {
+ /* push */
+- rtx dec = gen_rtx_PRE_DEC(REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, a7);
++ rtx dec = gen_rtx_PRE_DEC (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, a7);
+ rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, dec);
+- rtx set = gen_rtx_SET(mem, reg);
++ rtx set = gen_rtx_SET (mem, reg);
+ emit_insn_after (set, insn);
+ }
+ else
+ {
+ /* pop */
+- rtx dec = gen_rtx_POST_INC(REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, a7);
++ rtx dec = gen_rtx_POST_INC (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, a7);
+ rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, dec);
+- rtx set = gen_rtx_SET(reg, mem);
++ rtx set = gen_rtx_SET (reg, mem);
+ emit_insn_before (set, insn);
+ }
+ }
+ }
+ else
+ {
+- rtx parallel = gen_rtx_PARALLEL(VOIDmode, rtvec_alloc (regs.size () + add1 + clobbers.size ()));
++ rtx parallel = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (regs.size () + add1 + clobbers.size ()));
+ rtx plus;
+
+ int x = 0;
+@@ -3170,8 +3179,8 @@ opt_shrink_stack_frame (void)
+ /* no add if a5 is used with pop */
+ if (add1)
+ {
+- plus = gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, i < prologueend ? -x : x));
+- XVECEXP(parallel, 0, l) = gen_rtx_SET(a7, plus);
++ plus = gen_rtx_PLUS (SImode, a7, gen_rtx_CONST_INT (SImode, i < prologueend ? -x : x));
++ XVECEXP(parallel, 0, l) = gen_rtx_SET (a7, plus);
+ ++l;
+ }
+
+@@ -3183,10 +3192,10 @@ opt_shrink_stack_frame (void)
+ if (i < prologueend)
+ {
+ /* push */
+- plus = gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, -x));
++ plus = gen_rtx_PLUS (SImode, a7, gen_rtx_CONST_INT (SImode, -x));
+ x -= REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4;
+ rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, plus);
+- rtx set = gen_rtx_SET(mem, regs[k]);
++ rtx set = gen_rtx_SET (mem, regs[k]);
+ XVECEXP(parallel, 0, l) = set;
+ }
+ else
+@@ -3195,17 +3204,17 @@ opt_shrink_stack_frame (void)
+ if (usea5)
+ {
+ x += REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4;
+- plus = gen_rtx_PLUS(SImode, a5, gen_rtx_CONST_INT (SImode, a5offset + x));
++ plus = gen_rtx_PLUS (SImode, a5, gen_rtx_CONST_INT (SImode, a5offset + x));
+ rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, plus);
+- rtx set = gen_rtx_SET(regs[k], mem);
++ rtx set = gen_rtx_SET (regs[k], mem);
+ XVECEXP(parallel, 0, l) = set;
+ }
+ else
+ {
+- plus = x ? gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, x)) : a7;
++ plus = x ? gen_rtx_PLUS (SImode, a7, gen_rtx_CONST_INT (SImode, x)) : a7;
+ x += REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4;
+ rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, plus);
+- rtx set = gen_rtx_SET(regs[k], mem);
++ rtx set = gen_rtx_SET (regs[k], mem);
+ XVECEXP(parallel, 0, l) = set;
+ }
+ }
+@@ -3297,8 +3306,8 @@ opt_shrink_stack_frame (void)
+ if (ii.in_proepi () >= IN_EPILOGUE && ii.get_sp_offset () != 0)
+ {
+ log ("(f) adjusting exit sp\n");
+- rtx pattern = gen_rtx_SET(a7,
+- gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT(SImode, - ii.get_sp_offset())));
++ rtx pattern = gen_rtx_SET (
++ a7, gen_rtx_PLUS (SImode, a7, gen_rtx_CONST_INT (SImode, -ii.get_sp_offset ())));
+ emit_insn_before (pattern, ii.get_insn ());
+ }
+ }
+@@ -3316,7 +3325,7 @@ opt_shrink_stack_frame (void)
+ rtx pattern = PATTERN (ii.get_insn ());
+ unsigned sz = XVECLEN(pattern, 0);
+
+- rtx parallel = gen_rtx_PARALLEL(VOIDmode, rtvec_alloc (sz + 1));
++ rtx parallel = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (sz + 1));
+ unsigned n = 0;
+ for (unsigned j = 0; j < sz; ++j)
+ {
+@@ -3338,8 +3347,8 @@ opt_shrink_stack_frame (void)
+
+ rtx a = copy_reg (a7, -1);
+ a->frame_related = 1;
+- rtx plus = gen_rtx_PLUS(SImode, a, gen_rtx_CONST_INT (SImode, regs_total_size));
+- rtx set = gen_rtx_SET(a, plus);
++ rtx plus = gen_rtx_PLUS (SImode, a, gen_rtx_CONST_INT (SImode, regs_total_size));
++ rtx set = gen_rtx_SET (a, plus);
+ XVECEXP(parallel, 0, 0) = set;
+ SET_INSN_DELETED(ii.get_insn ());
+ ii.set_insn (emit_insn_after (parallel, ii.get_insn ()));
+@@ -3382,12 +3391,18 @@ track_regs ()
+ todo.erase (todo.begin ());
+
+ rtx * values = track->get_values ();
+- // track register aliases: know which register refers to this slot
+- // if a register changes, invalidate each referrer
+- std::multimap<unsigned, unsigned> r2r;
+- for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+- if (values[i] && REG_P(values[i]))
+- r2r.insert (std::make_pair (REGNO(values[i]), i));
++ // track register aliases: know which register is used in what slot
++ // if a register changes, invalidate each slot
++ std::multimap<unsigned, unsigned> reg2slot;
++ for (unsigned slot = 0; slot < FIRST_PSEUDO_REGISTER; ++slot)
++ if (values[slot])
++ {
++ insn_info vv;
++ vv.scan_rtx (values[slot]);
++ for (unsigned regno = 0, m = vv.get_myuse (); m; ++regno, m >>= 1)
++ if (m & 1)
++ reg2slot.insert (std::make_pair (regno, slot));
++ }
+
+ unsigned version = startpos;
+
+@@ -3406,10 +3421,16 @@ track_regs ()
+ if (ii.is_visited ())
+ {
+ ii.get_track_var ()->merge (track);
+- r2r.clear ();
+- for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+- if (values[i] && REG_P(values[i]))
+- r2r.insert (std::make_pair (REGNO(values[i]), i));
++ reg2slot.clear ();
++ for (unsigned slot = 0; slot < FIRST_PSEUDO_REGISTER; ++slot)
++ if (values[slot])
++ {
++ insn_info vv;
++ vv.scan_rtx (values[slot]);
++ for (unsigned regno = 0, m = vv.get_myuse (); m; ++regno, m >>= 1)
++ if (m & 1)
++ reg2slot.insert (std::make_pair (regno, slot));
++ }
+ }
+ else
+ {
+@@ -3429,16 +3450,16 @@ track_regs ()
+ unsigned def = ii.get_def ();
+ if (def)
+ {
+- for (int i = 0; i < 16; ++i)
+- if ((1 << i) & def)
++ for (int regno = 0; regno < 16; ++regno)
++ if ((1 << regno) & def)
+ {
+- values[i] = 0;
++ values[regno] = 0;
+ // invalidate all referring registers
+- for (std::multimap<unsigned, unsigned>::iterator j = r2r.find (i), k = j;
+- j != r2r.end () && j->first == k->first;)
++ for (std::multimap<unsigned, unsigned>::iterator j = reg2slot.find (regno), k = j;
++ j != reg2slot.end () && j->first == k->first;)
+ {
+ values[j->second] = 0;
+- r2r.erase (j++);
++ reg2slot.erase (j++);
+ }
+ }
+ }
+@@ -3475,11 +3496,11 @@ track_regs ()
+ {
+ int regno = ii.get_src_mem_regno ();
+ values[regno] = 0;
+- for (std::multimap<unsigned, unsigned>::iterator j = r2r.find (regno), k = j;
+- j != r2r.end () && j->first == k->first;)
++ for (std::multimap<unsigned, unsigned>::iterator j = reg2slot.find (regno), k = j;
++ j != reg2slot.end () && j->first == k->first;)
+ {
+ values[j->second] = 0;
+- r2r.erase (j++);
++ reg2slot.erase (j++);
+ }
+ }
+
+@@ -3496,11 +3517,11 @@ track_regs ()
+ {
+ int regno = ii.get_dst_mem_regno ();
+ values[regno] = 0;
+- for (std::multimap<unsigned, unsigned>::iterator j = r2r.find (regno), k = j;
+- j != r2r.end () && j->first == k->first;)
++ for (std::multimap<unsigned, unsigned>::iterator j = reg2slot.find (regno), k = j;
++ j != reg2slot.end () && j->first == k->first;)
+ {
+ values[j->second] = 0;
+- r2r.erase (j++);
++ reg2slot.erase (j++);
+ }
+ }
+
+@@ -3513,11 +3534,18 @@ track_regs ()
+ int dregno = ii.get_dst_regno ();
+ int sregno = ii.get_src_regno ();
+
+- // track r2r
+- if (dregno >= 0 && sregno >= 0)
++ // track reg2slot
++ if (dregno >= 0)
+ {
+- r2r.insert (std::make_pair (dregno, sregno));
+- r2r.insert (std::make_pair (sregno, dregno));
++ for (unsigned regno = 0, m = ii.get_myuse (); m; ++regno, m >>= 1)
++ if (m & 1)
++ reg2slot.insert (std::make_pair (regno, dregno));
++
++ if (sregno >= 0)
++ {
++ reg2slot.insert (std::make_pair (dregno, sregno));
++ reg2slot.insert (std::make_pair (sregno, dregno));
++ }
+ }
+
+ if (sregno >= 0)
+@@ -3738,14 +3766,14 @@ opt_absolute (void)
+ if (with_symbol)
+ {
+ if (base)
+- lea = gen_rtx_SET(
++ lea = gen_rtx_SET (
+ gen_raw_REG (SImode, regno),
+- gen_rtx_CONST(SImode, gen_rtx_PLUS(SImode, with_symbol, gen_rtx_CONST_INT (SImode, base))));
++ gen_rtx_CONST (SImode, gen_rtx_PLUS (SImode, with_symbol, gen_rtx_CONST_INT (SImode, base))));
+ else
+- lea = gen_rtx_SET(gen_raw_REG (SImode, regno), with_symbol);
++ lea = gen_rtx_SET (gen_raw_REG (SImode, regno), with_symbol);
+ }
+ else
+- lea = gen_rtx_SET(gen_raw_REG (SImode, regno), gen_rtx_CONST_INT (SImode, base));
++ lea = gen_rtx_SET (gen_raw_REG (SImode, regno), gen_rtx_CONST_INT (SImode, base));
+ rtx_insn * insn = emit_insn_before (lea, ii.get_insn ());
+ insn_info nn (insn);
+ nn.set_use (current_use);
+
+From 2950e164bd5d21b9654d111811ebb4bf75d9d618 Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Sun, 11 Jun 2017 21:58:31 +0100
+Subject: [PATCH 171/303] @V bump DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index e7d6b1e3aa50..be3338d16f6c 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170611-120626
++20170611-215803
+
+From 40d1ade0abfaae48c16daacb5baf2a23a56f3473 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 12 Jun 2017 13:14:52 +0200
+Subject: [PATCH 172/303] @B fix redundand load elimination: evaluate multiple
+ jumps to the same label correctly
+
+---
+ gcc/bbb-opts.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 9a0a3ac80e43..41b384b04cc6 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -3381,7 +3381,7 @@ track_regs ()
+ update_label2jump ();
+
+ // add entry point
+- std::map<unsigned, track_var *> todo;
++ std::multimap<unsigned, track_var *> todo;
+ todo.insert (std::make_pair (0, new track_var ()));
+
+ while (todo.begin () != todo.end ())
+@@ -3411,7 +3411,7 @@ track_regs ()
+ insn_info & ii = infos[index];
+
+ // already visited?
+- if (ii.is_visited () && ii.get_track_var ()->contains (track))
++ if (index != startpos && ii.is_visited () && ii.get_track_var ()->contains (track))
+ break;
+
+ // only keep common values at labels
+
+From d56d8369cfbc4f2db520ec76ba22479ab637c5bd Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Mon, 12 Jun 2017 13:45:19 +0100
+Subject: [PATCH 173/303] @V bump DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index be3338d16f6c..5d6c1ddcaf32 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170611-215803
++20170612-134455
+
+From 356944afa320b13bbe8b650404dfae48880851a7 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 13 Jun 2017 14:32:12 +0200
+Subject: [PATCH 174/303] @B fix link order
+
+---
+ gcc/config/m68k/m68kamigaos.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h
+index 50859a4c283f..beac496ab148 100644
+--- gcc/config/m68k/m68kamigaos.h
++++ gcc/config/m68k/m68kamigaos.h
+@@ -462,7 +462,7 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ "%{!p:%{!pg:-lc -lamiga -lc}} " \
+ "%{p:-lc_p} %{pg:-lc_p}"
+ #define LIB_LIBNIX_SPEC \
+- "-lnixmain -lnix -lstubs " \
++ "-lnixmain -lnix " \
+ "%{mcrt=*:-l%*} " \
+ "%{!mcrt=*:-lnix20} " \
+ "-lamiga " \
+
+From 7ec741afa4116beca5641b8f14f26c71c7ceb92d Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Tue, 13 Jun 2017 16:01:25 +0100
+Subject: [PATCH 175/303] @V bump DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 5d6c1ddcaf32..bbab26fe7028 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170612-134455
++20170613-160057
+
+From 91689b4bf59a1b051b8b137ccaad5df5b6fbae69 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 14 Jun 2017 22:33:56 +0200
+Subject: [PATCH 176/303] @N added opt_autoinc - replace offsets with auto incs
+
+---
+ gcc/bbb-opts.c | 308 ++++++++++++++++++++++++++++++++++++++++++++++++++-------
+ 1 file changed, 270 insertions(+), 38 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 41b384b04cc6..23d8fdb582c3 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -439,6 +439,18 @@ class insn_info
+ return dst_mem_reg ? REGNO(dst_mem_reg) : -1;
+ }
+
++ inline rtx
++ get_src_mem_reg () const
++ {
++ return src_mem_reg;
++ }
++
++ inline rtx
++ get_dst_mem_reg () const
++ {
++ return dst_mem_reg;
++ }
++
+ inline int
+ get_src_intval () const
+ {
+@@ -762,6 +774,12 @@ class insn_info
+ void
+ scan_rtx (rtx);
+
++ void
++ make_post_inc (int regno);
++
++ void
++ auto_inc_fixup (int regno, int size);
++
+ /* return bits for alternate free registers. */
+ unsigned
+ get_free_mask () const
+@@ -802,6 +820,64 @@ class insn_info
+ a5_to_a7 (rtx a7);
+ };
+
++void
++insn_info::make_post_inc (int regno)
++{
++ // convert into POST_INC
++// debug_rtx (insn);
++ rtx set = single_set (insn);
++ rtx mem = get_dst_mem_regno () == regno ? SET_DEST(set) : SET_SRC(set);
++ rtx reg = XEXP(mem, 0);
++ XEXP(mem, 0) = gen_rtx_POST_INC(SImode, reg);
++// debug_rtx (insn);
++
++ (get_dst_mem_regno () == regno ? dst_autoinc : src_autoinc) = GET_MODE_SIZE(mode);
++}
++
++void
++insn_info::auto_inc_fixup (int regno, int size)
++{
++// debug_rtx (insn);
++
++ rtx set = single_set (insn);
++
++ if (is_compare ())
++ set = SET_SRC(set);
++
++ // add to register
++ if (get_src_regno () == regno)
++ {
++ rtx src = SET_SRC(set);
++ if (get_src_intval () == size)
++ {
++ src_intval = 0;
++ src_plus = false;
++ SET_SRC(set) = XEXP(src, 0);
++ }
++ else
++ XEXP(src, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(src, 1)), src_intval -= size);
++ }
++ else
++ {
++ rtx mem = get_dst_mem_regno () == regno ? SET_DEST(set) : SET_SRC(set);
++ // goto mem if there is an op
++ if (get_src_mem_regno () == regno && src_op)
++ mem = XEXP(mem, 1);
++
++ rtx plus = XEXP(mem, 0);
++ if ((get_dst_mem_regno () == regno ? dst_mem_addr : src_mem_addr) == size)
++ {
++ XEXP(mem, 0) = XEXP(plus, 0);
++ (get_dst_mem_regno () == regno ? dst_mem_addr : src_mem_addr) = 0;
++ (get_dst_mem_regno () == regno ? dst_plus : src_plus) = false;
++ }
++ else
++ XEXP(plus, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(plus, 1)),
++ (get_dst_mem_regno () == regno ? dst_mem_addr : src_mem_addr) -= size);
++ }
++// debug_rtx (insn);
++}
++
+ track_var *
+ insn_info::get_track_var ()
+ {
+@@ -1126,7 +1202,7 @@ temp_reg_rename (std::vector<std::pair<rtx *, rtx> > & loc, rtx x, unsigned oldr
+ if (GET_CODE(z) == CLOBBER)
+ {
+ /* workaround for shared clobbers. */
+- XVECEXP(x, i, j) = z = gen_rtx_CLOBBER (GET_MODE(z), XEXP(z, 0));
++ XVECEXP(x, i, j) = z = gen_rtx_CLOBBER(GET_MODE(z), XEXP(z, 0));
+ }
+ temp_reg_rename (loc, z, oldregno, newregno);
+ }
+@@ -1268,7 +1344,7 @@ insn_info::a5_to_a7 (rtx a7)
+ rtx set = single_set (insn);
+ if (set)
+ {
+- SET_SRC(set) = gen_rtx_MEM (mode, gen_rtx_POST_INC (SImode, a7));
++ SET_SRC(set) = gen_rtx_MEM (mode, gen_rtx_POST_INC(SImode, a7));
+ return;
+ }
+ }
+@@ -1304,7 +1380,7 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol)
+ if (base == addr)
+ dst = gen_rtx_MEM (mode, reg);
+ else
+- dst = gen_rtx_MEM (mode, gen_rtx_PLUS (SImode, reg, gen_rtx_CONST_INT (SImode, offset)));
++ dst = gen_rtx_MEM (mode, gen_rtx_PLUS(SImode, reg, gen_rtx_CONST_INT (SImode, offset)));
+
+ dst_mem_reg = reg;
+ dst_mem = true;
+@@ -1322,13 +1398,13 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol)
+ if (base == addr)
+ src = gen_rtx_MEM (mode, reg);
+ else
+- src = gen_rtx_MEM (mode, gen_rtx_PLUS (SImode, reg, gen_rtx_CONST_INT (SImode, offset)));
++ src = gen_rtx_MEM (mode, gen_rtx_PLUS(SImode, reg, gen_rtx_CONST_INT (SImode, offset)));
+
+ /* some operation to the same value as dst. eg. eor #5,symbol+8 -> eor #5,8(ax) */
+ if (src_op)
+ {
+ if (src_ee)
+- src = gen_rtx_fmt_ee (src_op, mode, src, gen_rtx_CONST_INT (mode, src_intval));
++ src = gen_rtx_fmt_ee(src_op, mode, src, gen_rtx_CONST_INT (mode, src_intval));
+ else
+ {
+ if (src_op == SIGN_EXTEND)
+@@ -1336,7 +1412,7 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol)
+ PUT_MODE_RAW(src, mode == SImode ? HImode : mode == HImode ? QImode : SImode);
+ src->call = 1;
+ }
+- src = gen_rtx_fmt_e (src_op, mode, src);
++ src = gen_rtx_fmt_e(src_op, mode, src);
+ }
+ }
+
+@@ -1347,7 +1423,7 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol)
+ }
+ }
+
+- pattern = gen_rtx_SET (dst, src);
++ pattern = gen_rtx_SET(dst, src);
+ src->volatil = vola;
+
+ SET_INSN_DELETED(insn);
+@@ -2309,7 +2385,7 @@ opt_propagate_moves ()
+
+ for (unsigned k = 0; k < jump_out.size (); ++k)
+ {
+- rtx neu = gen_rtx_SET (
++ rtx neu = gen_rtx_SET(
+ dstj, gen_rtx_PLUS (Pmode, dsti, gen_rtx_CONST_INT (Pmode, fixups[k])));
+ emit_insn_after (neu, jump_out[k]);
+ }
+@@ -2386,7 +2462,7 @@ opt_strcpy ()
+ int num_clobbers_to_add = 0;
+ int insn_code_number;
+
+- rtx pattern = gen_rtx_SET (SET_DEST(single_set (reg2x)), SET_SRC(single_set (x2reg)));
++ rtx pattern = gen_rtx_SET(SET_DEST(single_set (reg2x)), SET_SRC(single_set (x2reg)));
+ rtx_insn * newinsn = make_insn_raw (pattern);
+ insn_code_number = recog (PATTERN (newinsn), newinsn, &num_clobbers_to_add);
+ if (insn_code_number >= 0 && check_asm_operands (PATTERN (newinsn)))
+@@ -2498,10 +2574,10 @@ opt_commute_add_move (void)
+ if (!REG_P(memreg) || REGNO(memreg) != REGNO(reg1src))
+ continue;
+
+- rtx pinc = gen_rtx_POST_INC (GET_MODE(dst), reg1dst);
++ rtx pinc = gen_rtx_POST_INC(GET_MODE(dst), reg1dst);
+ rtx newmem = replace_equiv_address_nv (dst, pinc);
+
+- rtx_insn * newinsn = make_insn_raw (gen_rtx_SET (reg1dst, reg1src));
++ rtx_insn * newinsn = make_insn_raw (gen_rtx_SET(reg1dst, reg1src));
+ if (recog (PATTERN (newinsn), newinsn, 0) < 0 || !check_asm_operands (PATTERN (newinsn)))
+ continue;
+
+@@ -2629,9 +2705,9 @@ opt_const_cmp_to_sub (void)
+ {
+ rtx copyreg = copy_reg (i1.get_dst_reg (), -1);
+ /* create the sub statement. */
+- rtx sub = gen_rtx_PLUS (i1.get_mode (), copyreg, gen_rtx_CONST_INT (i1.get_mode (), intval));
++ rtx sub = gen_rtx_PLUS(i1.get_mode (), copyreg, gen_rtx_CONST_INT (i1.get_mode (), intval));
+
+- rtx_insn * subinsn = make_insn_raw (gen_rtx_SET (copyreg, sub));
++ rtx_insn * subinsn = make_insn_raw (gen_rtx_SET(copyreg, sub));
+
+ int num_clobbers_to_add = 0;
+ int insn_code_number = recog (PATTERN (subinsn), subinsn, &num_clobbers_to_add);
+@@ -2648,8 +2724,8 @@ opt_const_cmp_to_sub (void)
+ subinsn = emit_insn_before (PATTERN (subinsn), i1.get_insn ());
+ i1.set_insn (subinsn);
+
+- rtx neu = gen_rtx_SET (cc0_rtx,
+- gen_rtx_COMPARE (i1.get_mode (), copyreg, gen_rtx_CONST_INT (i1.get_mode (), 0)));
++ rtx neu = gen_rtx_SET(cc0_rtx,
++ gen_rtx_COMPARE (i1.get_mode (), copyreg, gen_rtx_CONST_INT (i1.get_mode (), 0)));
+
+ emit_insn_before (neu, i2.get_insn ());
+
+@@ -2670,8 +2746,8 @@ opt_const_cmp_to_sub (void)
+ /* still a compare with 0 -> insert the sub. */
+ rtx copyreg = copy_reg (i1.get_dst_reg (), -1);
+ /* create the sub statement. */
+- rtx sub = gen_rtx_PLUS (i1.get_mode (), copyreg, c);
+- rtx set = gen_rtx_SET (copyreg, sub);
++ rtx sub = gen_rtx_PLUS(i1.get_mode (), copyreg, c);
++ rtx set = gen_rtx_SET(copyreg, sub);
+ emit_insn_before (set, pp.get_insn ());
+ }
+ else
+@@ -2743,7 +2819,7 @@ opt_merge_add (void)
+ rtx set = PATTERN (insn0);
+
+ // convert lea (-1,a0),a1 into move.l a0,a1
+- rtx_insn * newins0 = make_insn_raw (gen_rtx_SET (XEXP(set, 0), XEXP(XEXP(set, 1), 0)));
++ rtx_insn * newins0 = make_insn_raw (gen_rtx_SET(XEXP(set, 0), XEXP(XEXP(set, 1), 0)));
+ add_insn_after (newins0, insn0, 0);
+ SET_INSN_DELETED(insn0);
+ // update infos accordingly
+@@ -3151,24 +3227,24 @@ opt_shrink_stack_frame (void)
+ if (i < prologueend)
+ {
+ /* push */
+- rtx dec = gen_rtx_PRE_DEC (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, a7);
++ rtx dec = gen_rtx_PRE_DEC(REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, a7);
+ rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, dec);
+- rtx set = gen_rtx_SET (mem, reg);
++ rtx set = gen_rtx_SET(mem, reg);
+ emit_insn_after (set, insn);
+ }
+ else
+ {
+ /* pop */
+- rtx dec = gen_rtx_POST_INC (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, a7);
++ rtx dec = gen_rtx_POST_INC(REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, a7);
+ rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, dec);
+- rtx set = gen_rtx_SET (reg, mem);
++ rtx set = gen_rtx_SET(reg, mem);
+ emit_insn_before (set, insn);
+ }
+ }
+ }
+ else
+ {
+- rtx parallel = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (regs.size () + add1 + clobbers.size ()));
++ rtx parallel = gen_rtx_PARALLEL(VOIDmode, rtvec_alloc (regs.size () + add1 + clobbers.size ()));
+ rtx plus;
+
+ int x = 0;
+@@ -3179,8 +3255,8 @@ opt_shrink_stack_frame (void)
+ /* no add if a5 is used with pop */
+ if (add1)
+ {
+- plus = gen_rtx_PLUS (SImode, a7, gen_rtx_CONST_INT (SImode, i < prologueend ? -x : x));
+- XVECEXP(parallel, 0, l) = gen_rtx_SET (a7, plus);
++ plus = gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, i < prologueend ? -x : x));
++ XVECEXP(parallel, 0, l) = gen_rtx_SET(a7, plus);
+ ++l;
+ }
+
+@@ -3192,10 +3268,10 @@ opt_shrink_stack_frame (void)
+ if (i < prologueend)
+ {
+ /* push */
+- plus = gen_rtx_PLUS (SImode, a7, gen_rtx_CONST_INT (SImode, -x));
++ plus = gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, -x));
+ x -= REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4;
+ rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, plus);
+- rtx set = gen_rtx_SET (mem, regs[k]);
++ rtx set = gen_rtx_SET(mem, regs[k]);
+ XVECEXP(parallel, 0, l) = set;
+ }
+ else
+@@ -3204,17 +3280,17 @@ opt_shrink_stack_frame (void)
+ if (usea5)
+ {
+ x += REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4;
+- plus = gen_rtx_PLUS (SImode, a5, gen_rtx_CONST_INT (SImode, a5offset + x));
++ plus = gen_rtx_PLUS(SImode, a5, gen_rtx_CONST_INT (SImode, a5offset + x));
+ rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, plus);
+- rtx set = gen_rtx_SET (regs[k], mem);
++ rtx set = gen_rtx_SET(regs[k], mem);
+ XVECEXP(parallel, 0, l) = set;
+ }
+ else
+ {
+- plus = x ? gen_rtx_PLUS (SImode, a7, gen_rtx_CONST_INT (SImode, x)) : a7;
++ plus = x ? gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, x)) : a7;
+ x += REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4;
+ rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, plus);
+- rtx set = gen_rtx_SET (regs[k], mem);
++ rtx set = gen_rtx_SET(regs[k], mem);
+ XVECEXP(parallel, 0, l) = set;
+ }
+ }
+@@ -3306,7 +3382,7 @@ opt_shrink_stack_frame (void)
+ if (ii.in_proepi () >= IN_EPILOGUE && ii.get_sp_offset () != 0)
+ {
+ log ("(f) adjusting exit sp\n");
+- rtx pattern = gen_rtx_SET (
++ rtx pattern = gen_rtx_SET(
+ a7, gen_rtx_PLUS (SImode, a7, gen_rtx_CONST_INT (SImode, -ii.get_sp_offset ())));
+ emit_insn_before (pattern, ii.get_insn ());
+ }
+@@ -3325,7 +3401,7 @@ opt_shrink_stack_frame (void)
+ rtx pattern = PATTERN (ii.get_insn ());
+ unsigned sz = XVECLEN(pattern, 0);
+
+- rtx parallel = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (sz + 1));
++ rtx parallel = gen_rtx_PARALLEL(VOIDmode, rtvec_alloc (sz + 1));
+ unsigned n = 0;
+ for (unsigned j = 0; j < sz; ++j)
+ {
+@@ -3347,8 +3423,8 @@ opt_shrink_stack_frame (void)
+
+ rtx a = copy_reg (a7, -1);
+ a->frame_related = 1;
+- rtx plus = gen_rtx_PLUS (SImode, a, gen_rtx_CONST_INT (SImode, regs_total_size));
+- rtx set = gen_rtx_SET (a, plus);
++ rtx plus = gen_rtx_PLUS(SImode, a, gen_rtx_CONST_INT (SImode, regs_total_size));
++ rtx set = gen_rtx_SET(a, plus);
+ XVECEXP(parallel, 0, 0) = set;
+ SET_INSN_DELETED(ii.get_insn ());
+ ii.set_insn (emit_insn_after (parallel, ii.get_insn ()));
+@@ -3766,14 +3842,14 @@ opt_absolute (void)
+ if (with_symbol)
+ {
+ if (base)
+- lea = gen_rtx_SET (
++ lea = gen_rtx_SET(
+ gen_raw_REG (SImode, regno),
+ gen_rtx_CONST (SImode, gen_rtx_PLUS (SImode, with_symbol, gen_rtx_CONST_INT (SImode, base))));
+ else
+- lea = gen_rtx_SET (gen_raw_REG (SImode, regno), with_symbol);
++ lea = gen_rtx_SET(gen_raw_REG (SImode, regno), with_symbol);
+ }
+ else
+- lea = gen_rtx_SET (gen_raw_REG (SImode, regno), gen_rtx_CONST_INT (SImode, base));
++ lea = gen_rtx_SET(gen_raw_REG (SImode, regno), gen_rtx_CONST_INT (SImode, base));
+ rtx_insn * insn = emit_insn_before (lea, ii.get_insn ());
+ insn_info nn (insn);
+ nn.set_use (current_use);
+@@ -3800,6 +3876,158 @@ opt_absolute (void)
+ return change_count;
+ }
+
++/*
++ * Convert a series of reg with offset ( (ax), 4(ax), 8(ax), ...) into autoincx ( (ax+), (ax+), (ax+), ...)
++ *
++ * 1. search a mem(reg) without offset and either src or dst is using that reg
++ * 2. follow paths until reg is dead
++ * 3. if there is another mem(reg) with offset check that
++ * a) offset fits last mode size
++ * b) all remaining insn using that reg can be updated by
++ * i) decrement the offset
++ * ii) decrement the add value
++ */
++static unsigned
++opt_autoinc ()
++{
++ unsigned change_count = 0;
++ for (unsigned index = 0; index < infos.size (); ++index)
++ {
++ insn_info & ii = infos[index];
++
++ if (ii.in_proepi ())
++ continue;
++
++ rtx reg = 0;
++ if (ii.is_src_mem () && ii.get_src_mem_regno () >= 8 && !ii.get_src_mem_addr () && !ii.get_src_autoinc ()
++ && ii.get_src_mem_regno () != ii.get_dst_mem_regno ())
++ reg = ii.get_src_mem_reg ();
++ if (!reg && ii.is_dst_mem () && ii.get_dst_mem_regno () >= 8 && !ii.get_dst_intval () && !ii.get_dst_autoinc ()
++ && ii.get_src_mem_regno () != ii.get_dst_mem_regno ())
++ reg = ii.get_dst_mem_reg ();
++ if (!reg)
++ continue;
++
++ int regno = REGNO(reg);
++ int size = GET_MODE_SIZE(ii.get_mode ());
++ if (size > 4)
++ continue;
++
++// log ("starting auto_inc search for %s at %d\n", reg_names[regno], index);
++
++ // track all fixups to modify
++ std::set<unsigned> fixups;
++
++ // all paths to check
++ std::vector<unsigned> todo;
++ todo.push_back (index + 1);
++
++ bool match_size = false;
++ bool ok = true;
++ std::set<unsigned> visited;
++ while (ok && todo.size () > 0)
++ {
++ unsigned pos = todo[todo.size () - 1];
++ todo.pop_back ();
++
++ if (pos == index)
++ {
++ ok = false;
++ break;
++ }
++
++ if (visited.find (pos) != visited.end ())
++ continue;
++ visited.insert (pos);
++
++ for (; pos < infos.size (); ++pos)
++ {
++ insn_info & jj = infos[pos];
++
++ // run over labels
++ if (jj.is_label ())
++ continue;
++
++ // break if no longer user
++ if (!jj.is_use (regno))
++ break;
++
++ if (jj.in_proepi ())
++ {
++ ok = false;
++ break;
++ }
++
++ // break if in epilogue or add all labels
++ if (jj.is_jump ())
++ {
++ for (j2l_iterator j = jump2label.find (pos), k = j; j != jump2label.end () && j->first == k->first;
++ ++j)
++ todo.push_back (j->second);
++ continue;
++ }
++
++ // not used directly
++ if (!jj.is_myuse (regno))
++ continue;
++
++ // if reg is src reg, op must be add and addend must be large enough
++ if (jj.get_src_regno () == regno || jj.get_src_mem_regno () == regno)
++ {
++ if (jj.get_src_intval () < size || (jj.get_dst_mem_regno () == regno && jj.get_dst_addr () < size))
++ {
++ ok = false;
++ break;
++ }
++
++ if (jj.get_dst_addr () == size)
++ match_size = true;
++
++ fixups.insert (pos);
++ // end chain, if self assign
++ if (jj.get_dst_regno () == regno)
++ break;
++
++ continue;
++ }
++
++ if (jj.get_dst_mem_regno () == regno)
++ {
++ if (jj.get_dst_addr () < size)
++ {
++ ok = false;
++ break;
++ }
++ if (jj.get_dst_addr () == size)
++ match_size = true;
++ fixups.insert (pos);
++ }
++ }
++ }
++
++ if (!ok || !match_size || !fixups.size ())
++ continue;
++
++ log ("(i) auto_inc for %s at %d\n", reg_names[regno], index);
++
++ ii.make_post_inc (regno);
++
++ // fix all offsets / adds
++ for (std::set<unsigned>::iterator k = fixups.begin (); k != fixups.end (); ++k)
++ {
++// log ("(i) fixup at %d\n", *k);
++
++ insn_info & kk = infos[*k];
++
++ kk.auto_inc_fixup (regno, size);
++ }
++ ++change_count;
++ --index; // rerun insn to check src and dst
++ }
++
++ return change_count;
++}
++
+ namespace
+ {
+
+@@ -3870,6 +4098,7 @@ namespace
+ bool do_bb_reg_rename = strchr (string_bbb_opts, 'r') || strchr (string_bbb_opts, '+');
+ bool do_shrink_stack_frame = strchr (string_bbb_opts, 'f') || strchr (string_bbb_opts, '+');
+ bool do_absolute = strchr (string_bbb_opts, 'b') || strchr (string_bbb_opts, '+');
++ bool do_autoinc = strchr (string_bbb_opts, 'i') || strchr (string_bbb_opts, '+');
+
+ if (be_very_verbose)
+ log ("ENTER\n");
+@@ -3901,6 +4130,9 @@ namespace
+ if (do_elim_dead_assign && opt_elim_dead_assign ())
+ done = 0, update_insns ();
+
++ if (do_autoinc && opt_autoinc ())
++ done = 0, update_insns ();
++
+ if (do_bb_reg_rename)
+ {
+ while (opt_reg_rename ())
+
+From 210ee63e6fd9926deb41a28130f5c1b5e1dde8ba Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 14 Jun 2017 23:40:23 +0200
+Subject: [PATCH 177/303] @B handle compare correctly if converting to autoinc
+
+---
+ gcc/bbb-opts.c | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 23d8fdb582c3..b81c4db7f136 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -825,13 +825,18 @@ insn_info::make_post_inc (int regno)
+ {
+ // convert into POST_INC
+ // debug_rtx (insn);
+- rtx set = single_set (insn);
++ rtx set0 = single_set (insn);
++ rtx set = set0;
++ SET_INSN_DELETED(insn);
++ if (is_compare ())
++ set = SET_SRC(set);
+ rtx mem = get_dst_mem_regno () == regno ? SET_DEST(set) : SET_SRC(set);
+ rtx reg = XEXP(mem, 0);
+ XEXP(mem, 0) = gen_rtx_POST_INC(SImode, reg);
+-// debug_rtx (insn);
+
+ (get_dst_mem_regno () == regno ? dst_autoinc : src_autoinc) = GET_MODE_SIZE(mode);
++ insn = emit_insn_after(set0, insn);
++// debug_rtx (insn);
+ }
+
+ void
+@@ -839,8 +844,9 @@ insn_info::auto_inc_fixup (int regno, int size)
+ {
+ // debug_rtx (insn);
+
+- rtx set = single_set (insn);
+-
++ rtx set0 = single_set (insn);
++ rtx set = set0;
++ SET_INSN_DELETED(insn);
+ if (is_compare ())
+ set = SET_SRC(set);
+
+@@ -875,6 +881,7 @@ insn_info::auto_inc_fixup (int regno, int size)
+ XEXP(plus, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(plus, 1)),
+ (get_dst_mem_regno () == regno ? dst_mem_addr : src_mem_addr) -= size);
+ }
++ insn = emit_insn_after(set0, insn);
+ // debug_rtx (insn);
+ }
+
+
+From 9253b9cbb4784817cc6a112b4cb672b721ee131e Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 16 Jun 2017 13:05:58 +0200
+Subject: [PATCH 178/303] @B mark word/byte defs as use
+
+---
+ gcc/bbb-opts.c | 35 +++++++++++++++++------------------
+ 1 file changed, 17 insertions(+), 18 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index b81c4db7f136..1a5468418601 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -835,7 +835,7 @@ insn_info::make_post_inc (int regno)
+ XEXP(mem, 0) = gen_rtx_POST_INC(SImode, reg);
+
+ (get_dst_mem_regno () == regno ? dst_autoinc : src_autoinc) = GET_MODE_SIZE(mode);
+- insn = emit_insn_after(set0, insn);
++ insn = emit_insn_after (set0, insn);
+ // debug_rtx (insn);
+ }
+
+@@ -881,7 +881,7 @@ insn_info::auto_inc_fixup (int regno, int size)
+ XEXP(plus, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(plus, 1)),
+ (get_dst_mem_regno () == regno ? dst_mem_addr : src_mem_addr) -= size);
+ }
+- insn = emit_insn_after(set0, insn);
++ insn = emit_insn_after (set0, insn);
+ // debug_rtx (insn);
+ }
+
+@@ -1678,14 +1678,14 @@ update_insn_infos (void)
+ NOTICE_UPDATE_CC(PATTERN (insn), insn);
+ if (cc_status.value1 || cc_status.value2)
+ use.mark_def (FIRST_PSEUDO_REGISTER);
+-
+- // also check mode size if < 4, it's also a def.
+- if (ii.get_dst_reg () && GET_MODE_SIZE(ii.get_mode()) < 4)
+- use.mark_def (ii.get_dst_regno ());
+ }
+
++ // also check mode size if < 4, it's also a use.
++ if (pp.get_dst_reg () && GET_MODE_SIZE(pp.get_mode()) < 4)
++ use.mark_use (pp.get_dst_regno ());
++
+ /* mark not renameable in prologue/epilogue. */
+- if (infos[pos].in_proepi () != IN_CODE)
++ if (pp.in_proepi () != IN_CODE)
+ use.make_hard ();
+
+ ii.merge (use);
+@@ -3955,7 +3955,7 @@ opt_autoinc ()
+ if (jj.is_label ())
+ continue;
+
+- // break if no longer user
++ // break if no longer used
+ if (!jj.is_use (regno))
+ break;
+
+@@ -3965,7 +3965,7 @@ opt_autoinc ()
+ break;
+ }
+
+- // break if in epilogue or add all labels
++ // add all labels
+ if (jj.is_jump ())
+ {
+ for (j2l_iterator j = jump2label.find (pos), k = j; j != jump2label.end () && j->first == k->first;
+@@ -3991,24 +3991,24 @@ opt_autoinc ()
+ match_size = true;
+
+ fixups.insert (pos);
+- // end chain, if self assign
+- if (jj.get_dst_regno () == regno)
+- break;
+-
+- continue;
+ }
+-
+- if (jj.get_dst_mem_regno () == regno)
++ else if (jj.get_dst_mem_regno () == regno)
+ {
+ if (jj.get_dst_addr () < size)
+ {
+ ok = false;
+ break;
+ }
++
+ if (jj.get_dst_addr () == size)
+ match_size = true;
++
+ fixups.insert (pos);
+ }
++
++ // done if this is an add
++ if (ii.is_def (regno))
++ break;
+ }
+ }
+
+@@ -4023,11 +4023,10 @@ opt_autoinc ()
+ for (std::set<unsigned>::iterator k = fixups.begin (); k != fixups.end (); ++k)
+ {
+ // log ("(i) fixup at %d\n", *k);
+-
+ insn_info & kk = infos[*k];
+-
+ kk.auto_inc_fixup (regno, size);
+ }
++
+ ++change_count;
+ --index; // rerun insn to check src and dst
+ }
+
+From f0beccad3618cddcc3744347b5e000251394e1f4 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 16 Jun 2017 21:12:11 +0200
+Subject: [PATCH 179/303] @B reg rename backward start search must not run over
+ unconditional jumps
+
+---
+ gcc/bbb-opts.c | 89 ++++++++++++++++++++++++++++++++++++----------------------
+ 1 file changed, 55 insertions(+), 34 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 1a5468418601..f60232116968 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -71,6 +71,8 @@
+ #include <set>
+ #include <map>
+
++static int xx = 0;
++
+ bool be_very_verbose;
+ bool be_verbose;
+
+@@ -1487,7 +1489,7 @@ append_reg_usage (FILE * f, rtx_insn * insn)
+ insn_info & ii = *i->second;
+
+ if (f != stderr)
+- fprintf (f, "\n\t\t\t\t\t\t|");
++ fprintf (f, "\n\t\t\t\t\t|%d\t", ii.get_index ());
+
+ fprintf (f, "%c ",
+ ii.is_stack () ? 's' : ii.in_proepi () == IN_PROLOGUE ? 'p' : ii.in_proepi () >= IN_EPILOGUE ? 'e' : ' ');
+@@ -1680,9 +1682,10 @@ update_insn_infos (void)
+ use.mark_def (FIRST_PSEUDO_REGISTER);
+ }
+
+- // also check mode size if < 4, it's also a use.
+- if (pp.get_dst_reg () && GET_MODE_SIZE(pp.get_mode()) < 4)
+- use.mark_use (pp.get_dst_regno ());
++ // TODO: use 2 bits for data regs, to indicate mode size
++// // also check mode size if < 4, it's also a use for data registers.
++// if (pp.get_dst_reg () && pp.get_dst_regno () < 8 && GET_MODE_SIZE(pp.get_mode()) < 4)
++// use.mark_use (pp.get_dst_regno ());
+
+ /* mark not renameable in prologue/epilogue. */
+ if (pp.in_proepi () != IN_CODE)
+@@ -1908,12 +1911,17 @@ find_start (std::set<unsigned> & found, unsigned start, unsigned rename_regno)
+ {
+ unsigned startm1 = start - 1;
+
+- /* already searched. */
+- if (found.find (startm1) != found.end ())
+- break;
++// /* already searched. */
++// if (found.find (startm1) != found.end ())
++// break;
+
+ /* do not run over RETURNS */
+ insn_info & jj = infos[start];
++
++ /* stop at labels. If a label is a start pos, a search is maybe started again. */
++ if (jj.is_label ())
++ break;
++
+ insn_info & bb = infos[startm1];
+ if (jj.in_proepi () == IN_CODE && bb.in_proepi () >= IN_EPILOGUE)
+ break;
+@@ -1933,6 +1941,7 @@ find_start (std::set<unsigned> & found, unsigned start, unsigned rename_regno)
+ static unsigned
+ opt_reg_rename (void)
+ {
++ update_label2jump ();
+ // dump_insns ("rename", 1);
+ for (unsigned index = 0; index < infos.size (); ++index)
+ {
+@@ -1988,15 +1997,38 @@ opt_reg_rename (void)
+ {
+ i2i_iterator j = insn2info.find (i->second);
+ if (j == insn2info.end ())
+- continue;
++ {
++ mask = 0;
++ break;
++ }
+
+ unsigned start = j->second->get_index ();
+- if (!infos[start].is_use (rename_regno))
++ if (found.find (start) != found.end () || !infos[start].is_use (rename_regno))
+ continue;
+
++// printf ("label %d <- %d jump\n", pos, start); fflush (stdout);
++
+ start = find_start (found, start, rename_regno);
+ todo.insert (start);
+ }
++
++ /* if this label is at a start, check if it is reachable from the previous insn,
++ * and if, check for use then search start. */
++ if (pos == runpos && pos > 0)
++ {
++ insn_info & bb = infos[pos - 1];
++ rtx set = single_set (bb.get_insn ());
++ if (ANY_RETURN_P(bb.get_insn ())
++ || (set && SET_DEST(set) == pc_rtx && GET_CODE(SET_SRC(set)) != IF_THEN_ELSE))
++ continue;
++
++ if (bb.is_use (rename_regno))
++ {
++ unsigned start = find_start (found, pos - 1, rename_regno);
++ todo.insert (start);
++ }
++ }
++
+ continue;
+ }
+
+@@ -2035,37 +2067,21 @@ opt_reg_rename (void)
+ /* follow jump and/or next insn. */
+ if (JUMP_P(insn))
+ {
+- i2i_iterator j = insn2info.find ((rtx_insn *) JUMP_LABEL(insn));
+- if (j == insn2info.end ())
++ for (j2l_iterator i = jump2label.find (pos), k = i; i != jump2label.end () && i->first == k->first;
++ ++i)
+ {
+- /* whoops - label not found. */
+- mask = 0;
+- break;
+- }
++ unsigned label_index = i->second;
+
+- unsigned label_index = j->second->get_index ();
+- if (found.find (label_index) == found.end ())
+- {
+- /* if the rename_reg is used in the insn before.
+- * search the start.
+- */
++ /* add the label to the search list. */
+ insn_info & bb = infos[label_index + 1];
+- if (bb.is_use (rename_regno))
++ if (found.find (label_index) == found.end () && bb.is_use (rename_regno))
+ {
+- unsigned start = find_start (found, label_index, rename_regno);
+- todo.insert (start);
++// printf ("jump %d -> %d label\n", pos, label_index); fflush (stdout);
++ todo.insert (label_index);
+ }
+- todo.insert (label_index + 1);
+- }
+- rtx jmppattern = PATTERN (insn);
+- if (GET_CODE(jmppattern) == PARALLEL)
+- {
+- /* can't handle yet. Abort renaming. */
+- mask = 0;
+- break;
+ }
+-
+- rtx jmpsrc = XEXP(jmppattern, 1);
++ rtx set = single_set (insn);
++ rtx jmpsrc = SET_SRC(set);
+ if (!jmpsrc || GET_CODE(jmpsrc) != IF_THEN_ELSE)
+ break;
+ }
+@@ -4106,6 +4122,11 @@ namespace
+ bool do_absolute = strchr (string_bbb_opts, 'b') || strchr (string_bbb_opts, '+');
+ bool do_autoinc = strchr (string_bbb_opts, 'i') || strchr (string_bbb_opts, '+');
+
++ ++xx;
++ printf ("x: %d\n", xx);
++// if (xx <= 90 || xx > 93)
++// do_bb_reg_rename = false;
++
+ if (be_very_verbose)
+ log ("ENTER\n");
+
+
+From 77e758b888024c9df2267f0e344ff46efa763951 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 16 Jun 2017 21:53:51 +0200
+Subject: [PATCH 180/303] @B update jump2label lookup for autoincs
+
+---
+ gcc/bbb-opts.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index f60232116968..473dba829926 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -3914,6 +3914,9 @@ static unsigned
+ opt_autoinc ()
+ {
+ unsigned change_count = 0;
++
++ update_label2jump();
++
+ for (unsigned index = 0; index < infos.size (); ++index)
+ {
+ insn_info & ii = infos[index];
+@@ -4122,10 +4125,10 @@ namespace
+ bool do_absolute = strchr (string_bbb_opts, 'b') || strchr (string_bbb_opts, '+');
+ bool do_autoinc = strchr (string_bbb_opts, 'i') || strchr (string_bbb_opts, '+');
+
+- ++xx;
+- printf ("x: %d\n", xx);
+-// if (xx <= 90 || xx > 93)
+-// do_bb_reg_rename = false;
++// ++xx;
++// printf ("x: %d\n", xx);
++// if (xx <= 86 || xx > 90)
++// do_autoinc = false;
+
+ if (be_very_verbose)
+ log ("ENTER\n");
+
+From 669a03b0c64ae38eb9e231cabad983fd6e583325 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 16 Jun 2017 22:26:00 +0200
+Subject: [PATCH 181/303] @B cancel autoinc attempt if reg is directly used
+
+---
+ gcc/bbb-opts.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 473dba829926..85f1efea09ab 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -3915,7 +3915,7 @@ opt_autoinc ()
+ {
+ unsigned change_count = 0;
+
+- update_label2jump();
++ update_label2jump ();
+
+ for (unsigned index = 0; index < infos.size (); ++index)
+ {
+@@ -4024,6 +4024,11 @@ opt_autoinc ()
+
+ fixups.insert (pos);
+ }
++ else
++ {
++ ok = false;
++ break;
++ }
+
+ // done if this is an add
+ if (ii.is_def (regno))
+@@ -4127,7 +4132,7 @@ namespace
+
+ // ++xx;
+ // printf ("x: %d\n", xx);
+-// if (xx <= 86 || xx > 90)
++// if (xx <= 48 || xx > 54)
+ // do_autoinc = false;
+
+ if (be_very_verbose)
+
+From 206ae2727760bc76ca01b111f470b1ed70beced8 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sat, 17 Jun 2017 16:11:36 +0200
+Subject: [PATCH 182/303] @B autoinc is now checking the jumps to a label for
+ register usage
+
+---
+ gcc/bbb-opts.c | 18 ++++++++++++++++--
+ 1 file changed, 16 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 85f1efea09ab..db791406b0fb 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -3970,9 +3970,23 @@ opt_autoinc ()
+ {
+ insn_info & jj = infos[pos];
+
+- // run over labels
++ // check all jumps labels for register usage
+ if (jj.is_label ())
+- continue;
++ {
++ for (l2j_iterator j = label2jump.find (jj.get_insn ()->u2.insn_uid), k = j;
++ j != label2jump.end () && j->first == k->first; ++j)
++ {
++ insn_info * ll = insn2info.find (j->second)->second;
++ if (ll->is_use (regno))
++ {
++ ok = false;
++ break;
++ }
++ }
++ if (ok)
++ continue;
++ break;
++ }
+
+ // break if no longer used
+ if (!jj.is_use (regno))
+
+From bc3028a6f267699e0d6556b310a5cb75c2600e22 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sat, 17 Jun 2017 21:44:32 +0200
+Subject: [PATCH 183/303] @V bump DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index bbab26fe7028..e3b60659878c 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170613-160057
++20170617-214407
+
+From 98d760a8b0e4aaeccd8a37d6a55d425853628b1a Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 18 Jun 2017 13:09:59 +0200
+Subject: [PATCH 184/303] @B fix for some jump insns with parallel rtx (dbcc)
+
+---
+ gcc/bbb-opts.c | 16 +++++++++++++++-
+ 1 file changed, 15 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index db791406b0fb..f66256954f17 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -2081,7 +2081,21 @@ opt_reg_rename (void)
+ }
+ }
+ rtx set = single_set (insn);
+- rtx jmpsrc = SET_SRC(set);
++ if (!set)
++ {
++ // it's a parallel pattern - search the set pc = ...
++ rtx pat = PATTERN (insn);
++ for (int j = XVECLEN (pat, 0) - 1; j >= 0; j--)
++ {
++ rtx x = XVECEXP(pat, 0, j);
++ if (XEXP(x, 0) == pc_rtx)
++ {
++ set = x;
++ break;
++ }
++ }
++ }
++ rtx jmpsrc = set ? SET_SRC(set) : 0;
+ if (!jmpsrc || GET_CODE(jmpsrc) != IF_THEN_ELSE)
+ break;
+ }
+
+From 8bfc9663a96e6256cd360ab4355c8b66515f13f1 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 18 Jun 2017 13:11:04 +0200
+Subject: [PATCH 185/303] @R define _WCHAR_T_ if typedef-ing wchar_t
+
+---
+ gcc/ginclude/stddef.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/gcc/ginclude/stddef.h b/gcc/ginclude/stddef.h
+index d711530d0535..4f08f81a3ae0 100644
+--- gcc/ginclude/stddef.h
++++ gcc/ginclude/stddef.h
+@@ -325,6 +325,7 @@ typedef __rune_t rune_t;
+ #define __WCHAR_TYPE__ int
+ #endif
+ #ifndef __cplusplus
++#define _WCHAR_T_ int
+ typedef __WCHAR_TYPE__ wchar_t;
+ #endif
+ #endif
+
+From 3362e147aee470ae0715005e851264a30634aefc Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 18 Jun 2017 13:11:43 +0200
+Subject: [PATCH 186/303] @V bump DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index e3b60659878c..668d20875bcc 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170617-214407
++20170618-131118
+
+From c57b23b7b2ac0771437f22e7e9ca81ddbe0f04fa Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 20 Jun 2017 19:12:21 +0200
+Subject: [PATCH 187/303] @B fix autoinc generation if src op is present
+
+---
+ gcc/bbb-opts.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index f66256954f17..074669a4e844 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -833,6 +833,9 @@ insn_info::make_post_inc (int regno)
+ if (is_compare ())
+ set = SET_SRC(set);
+ rtx mem = get_dst_mem_regno () == regno ? SET_DEST(set) : SET_SRC(set);
++ if (src_op && get_src_mem_regno () == regno)
++ mem = XEXP(mem, 1);
++
+ rtx reg = XEXP(mem, 0);
+ XEXP(mem, 0) = gen_rtx_POST_INC(SImode, reg);
+
+
+From 85a73d1de786d310f2c9b8fad247f82c1c233e33 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 20 Jun 2017 19:13:37 +0200
+Subject: [PATCH 188/303] @V bump version
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 668d20875bcc..2c8dad4e8bed 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170618-131118
++20170620-191317
+
+From 8adf18dc9ae9c93578612b11935146fc572b662e Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 21 Jun 2017 13:34:32 +0200
+Subject: [PATCH 189/303] @B fix flow analysis with tail calls converted to
+ jumps
+
+---
+ gcc/bbb-opts.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 074669a4e844..f9e6e4008a44 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -1829,12 +1829,15 @@ update_insns ()
+ jump_table = 0;
+ ii.set_proepi (inproepilogue = IN_CODE);
+ if (infos.size () > 1)
+- scan_starts.insert (infos.size () - 1);
++ scan_starts.insert (infos.size () - 2);
+ }
+ else if (CALL_P(insn))
+ {
+- if (insn->jump)
++ if (insn->jump) {
+ ii.set_proepi (IN_EPILOGUE);
++ ii.mark_jump();
++ scan_starts.insert (infos.size () - 1);
++ }
+ ii.mark_call ();
+ if (inproepilogue)
+ {
+
+From ad1cbe3452a5355dde8947bc91c41145d56c19c2 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 21 Jun 2017 13:35:44 +0200
+Subject: [PATCH 190/303] @V bump DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 2c8dad4e8bed..e907b4926b96 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170620-191317
++20170621-133511
+
+From c1fff35716644f7270e12a819bad64a328ce530b Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 21 Jun 2017 19:32:08 +0200
+Subject: [PATCH 191/303] @B do not eliminate self updates, e.g. (a0),a0
+
+---
+ gcc/bbb-opts.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index f9e6e4008a44..352c14d18c6c 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -3716,7 +3716,7 @@ opt_elim_dead_assign (void)
+ ++change_count;
+ continue;
+ }
+- if (ii.get_src_op () == 0 && ii.get_dst_reg ())
++ if (ii.get_src_op () == 0 && ii.get_dst_reg () && !ii.is_use(ii.get_dst_regno()))
+ {
+ rtx cached_value = ii.get_track_var ()->get_values ()[ii.get_dst_regno ()];
+ rtx cached_value2 = 0;
+
+From f573652f798f9ea72796cced3b8044d3dafd7bad Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 22 Jun 2017 15:20:24 +0200
+Subject: [PATCH 192/303] @B fix flow analysis, @D V dumps now no index
+ numbers, vV dumps index numbers into asm
+
+---
+ gcc/bbb-opts.c | 51 +++++++++++++++++++++++++++++++++++----------------
+ 1 file changed, 35 insertions(+), 16 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 352c14d18c6c..8b49637f6c09 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -73,7 +73,7 @@
+
+ static int xx = 0;
+
+-bool be_very_verbose;
++int be_very_verbose;
+ bool be_verbose;
+
+ extern struct lang_hooks lang_hooks;
+@@ -1468,13 +1468,13 @@ is_reg_dead (unsigned regno, unsigned _pos)
+ // skip labels.
+ for (unsigned pos = _pos + 1; pos < infos.size (); ++pos)
+ {
+- insn_info & ii0 = infos[pos];
++ insn_info & ii = infos[pos];
+ // skip entries without info
+- if (ii0.is_empty ())
++ if (ii.is_empty ())
+ continue;
+
+ // not dead if usage is reported in the next statement
+- return !ii0.is_use (regno) && !ii0.is_hard (regno);
++ return !ii.is_use (regno) && !ii.is_hard (regno);
+ }
+ return true;
+ }
+@@ -1492,10 +1492,14 @@ append_reg_usage (FILE * f, rtx_insn * insn)
+ insn_info & ii = *i->second;
+
+ if (f != stderr)
+- fprintf (f, "\n\t\t\t\t\t|%d\t", ii.get_index ());
++ {
++ if (be_very_verbose > 1)
++ fprintf (f, "\n\t\t\t\t\t|%d\t", ii.get_index ());
++ else
++ fprintf (f, "\n\t\t\t\t\t|\t", ii.get_index ());
++ }
+
+- fprintf (f, "%c ",
+- ii.is_stack () ? 's' : ii.in_proepi () == IN_PROLOGUE ? 'p' : ii.in_proepi () >= IN_EPILOGUE ? 'e' : ' ');
++ fprintf (f, "%c ", ii.in_proepi () == IN_PROLOGUE ? 'p' : ii.in_proepi () >= IN_EPILOGUE ? 'e' : ' ');
+
+ for (int j = 0; j < 8; ++j)
+ if (ii.is_use (j) || ii.is_def (j))
+@@ -1829,15 +1833,16 @@ update_insns ()
+ jump_table = 0;
+ ii.set_proepi (inproepilogue = IN_CODE);
+ if (infos.size () > 1)
+- scan_starts.insert (infos.size () - 2);
++ scan_starts.insert (infos.size () - 1);
+ }
+ else if (CALL_P(insn))
+ {
+- if (insn->jump) {
+- ii.set_proepi (IN_EPILOGUE);
+- ii.mark_jump();
+- scan_starts.insert (infos.size () - 1);
+- }
++ if (insn->jump)
++ {
++ ii.set_proepi (IN_EPILOGUE);
++ ii.mark_jump ();
++ scan_starts.insert (infos.size () - 1);
++ }
+ ii.mark_call ();
+ if (inproepilogue)
+ {
+@@ -2114,6 +2119,7 @@ opt_reg_rename (void)
+ int newregno = bit2regno (mask);
+
+ /* check the renamed insns. */
++ std::vector<unsigned> positions;
+ std::vector<std::pair<rtx *, rtx> > locs;
+ std::vector<std::pair<rtx *, rtx> > patch;
+ bool ok = true;
+@@ -2138,6 +2144,7 @@ opt_reg_rename (void)
+ *j->first = j->second;
+ }
+
++ positions.push_back (*i);
+ locs.clear ();
+ }
+ }
+@@ -2148,6 +2155,14 @@ opt_reg_rename (void)
+ log ("(r) opt_reg_rename %s -> %s (%d locs, start at %d)\n", reg_names[oldregno], reg_names[newregno],
+ patch.size (), index);
+
++ if (be_verbose)
++ {
++ for (std::vector<unsigned>::iterator i = positions.begin (); i != positions.end (); ++i)
++ printf ("%d ", *i);
++ printf ("\n");
++ fflush (stdout);
++ }
++
+ /* apply all changes. */
+ for (std::vector<std::pair<rtx *, rtx> >::iterator j = patch.begin (); j != patch.end (); ++j)
+ *j->first = j->second;
+@@ -3716,7 +3731,7 @@ opt_elim_dead_assign (void)
+ ++change_count;
+ continue;
+ }
+- if (ii.get_src_op () == 0 && ii.get_dst_reg () && !ii.is_use(ii.get_dst_regno()))
++ if (ii.get_src_op () == 0 && ii.get_dst_reg () && !ii.is_use (ii.get_dst_regno ()))
+ {
+ rtx cached_value = ii.get_track_var ()->get_values ()[ii.get_dst_regno ()];
+ rtx cached_value2 = 0;
+@@ -4150,8 +4165,12 @@ namespace
+ unsigned
+ pass_bbb_optimizations::execute_bbb_optimizations (void)
+ {
+- be_very_verbose = strchr (string_bbb_opts, 'V');
+- be_verbose = be_very_verbose || strchr (string_bbb_opts, 'v');
++ be_very_verbose = strchr (string_bbb_opts, 'V') != 0;
++ be_verbose = strchr (string_bbb_opts, 'v') != 0;
++ if (be_verbose && be_very_verbose)
++ ++be_very_verbose;
++ if (be_very_verbose)
++ be_verbose = true;
+
+ bool do_opt_strcpy = strchr (string_bbb_opts, 's') || strchr (string_bbb_opts, '+');
+ bool do_commute_add_move = strchr (string_bbb_opts, 'a') || strchr (string_bbb_opts, '+');
+
+From acdf0eba2196c10905cc07af78fba0eca5f457ca Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 22 Jun 2017 15:21:40 +0200
+Subject: [PATCH 193/303] @B support trap and preserve all registers
+
+---
+ gcc/bbb-opts.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 8b49637f6c09..35ebc7d770e6 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -979,6 +979,13 @@ insn_info::scan_rtx (rtx x)
+ return;
+ }
+
++ if (code == TRAP_IF)
++ {
++ /* mark all registers used. */
++ hard = use = myuse = (1 << FIRST_PSEUDO_REGISTER) - 1;
++ return;
++ }
++
+ const char *fmt = GET_RTX_FORMAT(code);
+ for (int i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ {
+
+From dccd1ea371e35241057b86bdf90cf8be60d2083c Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 22 Jun 2017 16:00:20 +0200
+Subject: [PATCH 194/303] @V bump DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index e907b4926b96..95b694bea9d1 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170621-133511
++20170622-160003
+
+From 95ee80db20652f6647cf6f30da3c7c74e7160a62 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 22 Jun 2017 16:01:04 +0200
+Subject: [PATCH 195/303] @B eliminate sp assignments after stack frame
+ handling is done
+
+---
+ gcc/bbb-opts.c | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 35ebc7d770e6..f50c8578f923 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -3715,7 +3715,7 @@ track_regs ()
+ * delete those insns.
+ */
+ static unsigned
+-opt_elim_dead_assign (void)
++opt_elim_dead_assign (unsigned blocked_regno)
+ {
+ track_regs ();
+
+@@ -3731,14 +3731,15 @@ opt_elim_dead_assign (void)
+ if (!set)
+ continue;
+
+- if (ii.get_dst_reg () && is_reg_dead (ii.get_dst_regno (), index))
++ if (ii.get_dst_reg () && ii.get_dst_regno () != blocked_regno && is_reg_dead (ii.get_dst_regno (), index))
+ {
+ log ("(e) %d: eliminate dead assign to %s\n", index, reg_names[ii.get_dst_regno ()]);
+ SET_INSN_DELETED(insn);
+ ++change_count;
+ continue;
+ }
+- if (ii.get_src_op () == 0 && ii.get_dst_reg () && !ii.is_use (ii.get_dst_regno ()))
++ if (ii.get_src_op () == 0 && ii.get_dst_reg () && ii.get_dst_regno () != blocked_regno
++ && !ii.is_use (ii.get_dst_regno ()))
+ {
+ rtx cached_value = ii.get_track_var ()->get_values ()[ii.get_dst_regno ()];
+ rtx cached_value2 = 0;
+@@ -4222,7 +4223,7 @@ namespace
+ if (do_absolute && opt_absolute ())
+ done = 0, update_insns ();
+
+- if (do_elim_dead_assign && opt_elim_dead_assign ())
++ if (do_elim_dead_assign && opt_elim_dead_assign (STACK_POINTER_REGNUM))
+ done = 0, update_insns ();
+
+ if (do_autoinc && opt_autoinc ())
+@@ -4246,6 +4247,10 @@ namespace
+ if (opt_shrink_stack_frame ())
+ update_insns ();
+ }
++
++ /* elim stack pointer stuff last. */
++ if (do_elim_dead_assign)
++ opt_elim_dead_assign (FIRST_PSEUDO_REGISTER);
+ }
+ if (r && be_verbose)
+ log ("no bbb optimization code %d\n", r);
+
+From 335edd4fe233548c3353bd7e49fd374fefb6b67c Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 5 Jul 2017 09:10:22 +0200
+Subject: [PATCH 196/303] @B fixed regrename: start search was not triggered if
+ the assignment is before a label
+
+---
+ gcc/bbb-opts.c | 26 +++++++++++++-------------
+ 1 file changed, 13 insertions(+), 13 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index f50c8578f923..247fc522aaa2 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -1922,17 +1922,13 @@ is_reg_touched_between (unsigned regno, int from, int to)
+ * search backward and find the initial assignment for that regno.
+ */
+ static unsigned
+-find_start (std::set<unsigned> & found, unsigned start, unsigned rename_regno)
++find_start (unsigned start, unsigned rename_regno)
+ {
+ /* search the start. */
+ while (start > 0)
+ {
+ unsigned startm1 = start - 1;
+
+-// /* already searched. */
+-// if (found.find (startm1) != found.end ())
+-// break;
+-
+ /* do not run over RETURNS */
+ insn_info & jj = infos[start];
+
+@@ -1995,6 +1991,7 @@ opt_reg_rename (void)
+ unsigned runpos = *todo.begin ();
+ todo.erase (todo.begin ());
+
++// printf ("runpos %d \n", runpos); fflush (stdout);
+ for (unsigned pos = runpos; mask && pos < infos.size (); ++pos)
+ {
+ /* already searched. */
+@@ -2020,19 +2017,19 @@ opt_reg_rename (void)
+ break;
+ }
+
+- unsigned start = j->second->get_index ();
+- if (found.find (start) != found.end () || !infos[start].is_use (rename_regno))
++ unsigned startat = j->second->get_index ();
++ if (found.find (startat) != found.end () || !infos[startat].is_use (rename_regno))
+ continue;
+
+-// printf ("label %d <- %d jump\n", pos, start); fflush (stdout);
+
+- start = find_start (found, start, rename_regno);
++ unsigned start = find_start (startat, rename_regno);
++// printf ("label %d <- jump %d : start %d\n", pos, startat, start); fflush (stdout);
+ todo.insert (start);
+ }
+
+ /* if this label is at a start, check if it is reachable from the previous insn,
+ * and if, check for use then search start. */
+- if (pos == runpos && pos > 0)
++ if (pos > 0)
+ {
+ insn_info & bb = infos[pos - 1];
+ rtx set = single_set (bb.get_insn ());
+@@ -2040,10 +2037,13 @@ opt_reg_rename (void)
+ || (set && SET_DEST(set) == pc_rtx && GET_CODE(SET_SRC(set)) != IF_THEN_ELSE))
+ continue;
+
+- if (bb.is_use (rename_regno))
++// printf ("label start check %d use %d\n", pos, bb.is_use (rename_regno) || bb.is_def(rename_regno)); fflush (stdout);
++
++ if (bb.is_use (rename_regno) || bb.is_def(rename_regno))
+ {
+- unsigned start = find_start (found, pos - 1, rename_regno);
++ unsigned start = find_start (pos - 1, rename_regno);
+ todo.insert (start);
++// printf ("label %d : start %d \n", pos, start); fflush (stdout);
+ }
+ }
+
+@@ -2094,7 +2094,7 @@ opt_reg_rename (void)
+ insn_info & bb = infos[label_index + 1];
+ if (found.find (label_index) == found.end () && bb.is_use (rename_regno))
+ {
+-// printf ("jump %d -> %d label\n", pos, label_index); fflush (stdout);
++// printf ("jump %d -> label %d \n", pos, label_index); fflush (stdout);
+ todo.insert (label_index);
+ }
+ }
+
+From 5180bf61c8f24d190fe51722d78f69b4fb566065 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 5 Jul 2017 20:20:50 +0200
+Subject: [PATCH 197/303] @B add ctype<char>::~ctype()
+
+---
+ libstdc++-v3/config/os/newlib/ctype_configure_char.cc | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/libstdc++-v3/config/os/newlib/ctype_configure_char.cc b/libstdc++-v3/config/os/newlib/ctype_configure_char.cc
+index 903de5625d77..3198a3069fc6 100644
+--- libstdc++-v3/config/os/newlib/ctype_configure_char.cc
++++ libstdc++-v3/config/os/newlib/ctype_configure_char.cc
+@@ -65,6 +65,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
+ _M_narrow_ok = 0;
+ }
+
++ ctype<char>::~ctype()
++ {
++ }
++
+ char
+ ctype<char>::do_toupper(char __c) const
+ {
+
+From f088c99da4c5cdb2b86c57475a2fddbb76deba6f Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 6 Jul 2017 23:38:50 +0200
+Subject: [PATCH 198/303] @B resolve ctype vtable issue and avoid duplicate
+ definition
+
+---
+ libstdc++-v3/config/os/newlib/ctype_configure_char.cc | 5 +++++
+ libstdc++-v3/configure.host | 4 ++--
+ libstdc++-v3/src/c++11/ctype.cc | 3 +++
+ 3 files changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/libstdc++-v3/config/os/newlib/ctype_configure_char.cc b/libstdc++-v3/config/os/newlib/ctype_configure_char.cc
+index 3198a3069fc6..5543759efa51 100644
+--- libstdc++-v3/config/os/newlib/ctype_configure_char.cc
++++ libstdc++-v3/config/os/newlib/ctype_configure_char.cc
+@@ -65,9 +65,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
+ _M_narrow_ok = 0;
+ }
+
++#ifdef TARGET_AMIGA
+ ctype<char>::~ctype()
+ {
++ _S_destroy_c_locale(_M_c_locale_ctype);
++ if (_M_del)
++ delete[] this->table();
+ }
++#endif
+
+ char
+ ctype<char>::do_toupper(char __c) const
+diff --git a/libstdc++-v3/configure.host b/libstdc++-v3/configure.host
+index 354b1c7ead46..13444bc5a4cf 100644
+--- libstdc++-v3/configure.host
++++ libstdc++-v3/configure.host
+@@ -228,8 +228,8 @@ case "${host_os}" in
+ ;;
+ amiga*)
+ os_include_dir="os/newlib"
+- CXXFLAGS="${CXXFLAGS} -noixemul"
+- CPPFLAGS="${CPPFLAGS} -noixemul"
++# CXXFLAGS="${CXXFLAGS} -noixemul"
++# CPPFLAGS="${CPPFLAGS} -noixemul"
+ ;;
+ bsd*)
+ # Plain BSD attempts to share FreeBSD files.
+diff --git a/libstdc++-v3/src/c++11/ctype.cc b/libstdc++-v3/src/c++11/ctype.cc
+index fa370681dad5..6867e61e8b7d 100644
+--- libstdc++-v3/src/c++11/ctype.cc
++++ libstdc++-v3/src/c++11/ctype.cc
+@@ -51,12 +51,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ const size_t ctype<char>::table_size;
+
++#ifndef TARGET_AMIGA
++/* moved to ctype_configure_char */
+ ctype<char>::~ctype()
+ {
+ _S_destroy_c_locale(_M_c_locale_ctype);
+ if (_M_del)
+ delete[] this->table();
+ }
++#endif
+
+ // Fill in the narrowing cache and flag whether all values are
+ // valid or not. _M_narrow_ok is set to 2 if memcpy can't
+
+From c4e78d720943ce032d2ccfff2ceea56164403d29 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 7 Jul 2017 21:57:40 +0200
+Subject: [PATCH 199/303] @B restore -noixemul in libstdc++v3
+
+---
+ gcc/DATESTAMP | 2 +-
+ libstdc++-v3/configure.host | 4 ++--
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 95b694bea9d1..58e8c652ab1b 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170622-160003
++20170707-215619
+diff --git a/libstdc++-v3/configure.host b/libstdc++-v3/configure.host
+index 13444bc5a4cf..354b1c7ead46 100644
+--- libstdc++-v3/configure.host
++++ libstdc++-v3/configure.host
+@@ -228,8 +228,8 @@ case "${host_os}" in
+ ;;
+ amiga*)
+ os_include_dir="os/newlib"
+-# CXXFLAGS="${CXXFLAGS} -noixemul"
+-# CPPFLAGS="${CPPFLAGS} -noixemul"
++ CXXFLAGS="${CXXFLAGS} -noixemul"
++ CPPFLAGS="${CPPFLAGS} -noixemul"
+ ;;
+ bsd*)
+ # Plain BSD attempts to share FreeBSD files.
+
+From 0fe16b4eac1770fc611f217ca4c9aafdb0065f7e Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 7 Jul 2017 23:01:11 +0200
+Subject: [PATCH 200/303] @B fix v2 ctype dtor
+
+---
+ libstdc++-v3/config/os/newlib/ctype_configure_char.cc | 2 +-
+ libstdc++-v3/src/c++11/ctype.cc | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/libstdc++-v3/config/os/newlib/ctype_configure_char.cc b/libstdc++-v3/config/os/newlib/ctype_configure_char.cc
+index 5543759efa51..ed0c757d42f8 100644
+--- libstdc++-v3/config/os/newlib/ctype_configure_char.cc
++++ libstdc++-v3/config/os/newlib/ctype_configure_char.cc
+@@ -65,7 +65,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
+ _M_narrow_ok = 0;
+ }
+
+-#ifdef TARGET_AMIGA
++#ifdef __AMIGA__
+ ctype<char>::~ctype()
+ {
+ _S_destroy_c_locale(_M_c_locale_ctype);
+diff --git a/libstdc++-v3/src/c++11/ctype.cc b/libstdc++-v3/src/c++11/ctype.cc
+index 6867e61e8b7d..f80e83034255 100644
+--- libstdc++-v3/src/c++11/ctype.cc
++++ libstdc++-v3/src/c++11/ctype.cc
+@@ -51,7 +51,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ const size_t ctype<char>::table_size;
+
+-#ifndef TARGET_AMIGA
++#ifndef __AMIGA__
+ /* moved to ctype_configure_char */
+ ctype<char>::~ctype()
+ {
+
+From 8e243494b547e0452be69f9decc094f5cdf390db Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 11 Jul 2017 12:26:30 +0200
+Subject: [PATCH 201/303] @B fixed opt_const_cmp_to_sub with chained compares:
+ exit labels were not tested.
+
+---
+ gcc/bbb-opts.c | 14 +++++++++++---
+ 1 file changed, 11 insertions(+), 3 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 247fc522aaa2..365eec1c7280 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -2717,6 +2717,15 @@ opt_const_cmp_to_sub (void)
+ if (pp.get_dst_regno () != i1.get_dst_regno ())
+ continue;
+ lastsubval = pp.get_src_intval ();
++
++ // but still check for usage after this jump
++ j2l_iterator l = jump2label.find(index + 2);
++ if (l == jump2label.end())
++ continue;
++
++ insn_info & label = infos[l->second + 1];
++ if (label.is_use (i1.get_dst_regno ()))
++ continue;
+ }
+ else if (!is_reg_dead (i1.get_dst_regno (), index))
+ continue;
+@@ -2752,9 +2761,8 @@ opt_const_cmp_to_sub (void)
+ if (!i2.is_jump ())
+ continue;
+
+- rtx_insn * jump = i2.get_insn ();
+- rtx jmppattern = PATTERN (jump);
+- if (GET_RTX_LENGTH (GET_CODE(jmppattern)) < 2)
++ rtx jmppattern = single_set (i2.get_insn ());
++ if (!jmppattern)
+ continue;
+
+ rtx jmpsrc = XEXP(jmppattern, 1);
+
+From be3b4203f780465f6221fe829df769638bb989c6 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 11 Jul 2017 12:27:44 +0200
+Subject: [PATCH 202/303] @N create labels and storage needed for exception
+ handling
+
+---
+ gcc/dwarf2out.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
+index 1357bf24a125..566aaaf4e370 100644
+--- gcc/dwarf2out.c
++++ gcc/dwarf2out.c
+@@ -469,6 +469,16 @@ switch_to_eh_frame_section (bool back ATTRIBUTE_UNUSED)
+ eh_frame_section = ((flags == SECTION_WRITE)
+ ? data_section : readonly_data_section);
+ #endif /* EH_FRAME_SECTION_NAME */
++
++#ifdef TARGET_AMIGA
++ switch_to_section (data_section);
++ fputs("\t__EH_FRAME_OBJECT__:\n\t.long 0\n\t.long 0\n\t.long 0\n\t.long 0\n\t.long 0\n\t.long 0\n", asm_out_file);
++ fputs("\t.stabs \"__EH_FRAME_OBJECTS__\",24,0,0,__EH_FRAME_OBJECT__\n", asm_out_file);
++
++ switch_to_section (eh_frame_section);
++ ASM_OUTPUT_LABEL (asm_out_file, "_EH_FRAME_BEGIN__");
++ fputs("\t.stabs \"__EH_FRAME_BEGINS__\",22,0,0,__EH_FRAME_BEGIN__\n", asm_out_file);
++#endif
+ }
+
+ switch_to_section (eh_frame_section);
+
+From 7c0d506d800c3a33d3a9f8b7da0a5be3e4a72178 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 11 Jul 2017 12:30:55 +0200
+Subject: [PATCH 203/303] @N create startup code to init exception structures,
+ link some glue code (cxxglue) if g++ is used to init exceptions.
+
+---
+ gcc/cp/g++spec.c | 16 +++++++++++++++-
+ libgcc/config/m68k/cxxglue.c | 22 ++++++++++++++++++++++
+ libgcc/config/m68k/t-glue | 5 +++++
+ 3 files changed, 42 insertions(+), 1 deletion(-)
+ create mode 100644 libgcc/config/m68k/cxxglue.c
+ create mode 100644 libgcc/config/m68k/t-glue
+
+diff --git a/gcc/cp/g++spec.c b/gcc/cp/g++spec.c
+index 03cbde090cb3..c6fc90d546d6 100644
+--- gcc/cp/g++spec.c
++++ gcc/cp/g++spec.c
+@@ -262,7 +262,7 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
+ #endif
+
+ /* Add one for shared_libgcc or extra static library. */
+- num_args = argc + added + need_math + (library > 0) * 4 + 1;
++ num_args = argc + added + need_math + (library > 0) * 5 + 1;
+ new_decoded_options = XNEWVEC (struct cl_decoded_option, num_args);
+
+ i = 0;
+@@ -347,6 +347,20 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
+ CL_DRIVER, &new_decoded_options[j]);
+ added_libraries++;
+ j++;
++
++#ifdef TARGET_AMIGA
++ {
++ extern const char *
++ amiga_m68k_prefix_func (int argc, const char ** argv);
++ char const * cxxglue = "../lib/gcc/m68k-amigaos/"
++ DEFAULT_TARGET_VERSION
++ "/cxxglue.o";
++ char const * p = amiga_m68k_prefix_func (1, &cxxglue);
++ generate_option_input_file (p, &new_decoded_options[j]);
++ ++j;
++ }
++#endif
++
+ /* Add target-dependent static library, if necessary. */
+ if ((static_link || library > 1) && LIBSTDCXX_STATIC != NULL)
+ {
+diff --git a/libgcc/config/m68k/cxxglue.c b/libgcc/config/m68k/cxxglue.c
+new file mode 100644
+index 000000000000..2a4e6374d088
+--- /dev/null
++++ libgcc/config/m68k/cxxglue.c
+@@ -0,0 +1,22 @@
++#include "stabs.h"
++
++extern void __register_frame_info(void *, void *);
++extern void * _EH_FRAME_BEGINS__;
++extern void * _EH_FRAME_OBJECTS__;
++
++void __init_eh() {
++ void ** frame = &_EH_FRAME_BEGINS__;
++ void ** object = &_EH_FRAME_OBJECTS__;
++
++ int n = *(int *)frame++;
++ int m = *(int *)object++;
++ if (n != m)
++ return;
++
++ while (n--) {
++ __register_frame_info(*frame++, *object++);
++ }
++}
++
++ADD2INIT(__init_eh,127);
++
+diff --git a/libgcc/config/m68k/t-glue b/libgcc/config/m68k/t-glue
+new file mode 100644
+index 000000000000..e65335f2e5f7
+--- /dev/null
++++ libgcc/config/m68k/t-glue
+@@ -0,0 +1,5 @@
++cxxglue.o: $(srcdir)/config/m68k/cxxglue.c
++ $(CC) $(CFLAGS) -c $<
++
++EXTRA_PARTS=cxxglue.o
++
+
+From 54f7a6eb27c74a7f4358a32c4f018ca12512bab0 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 11 Jul 2017 12:38:25 +0200
+Subject: [PATCH 204/303] @R do not add cxxglue if -fno-exceptions is specified
+
+---
+ gcc/cp/g++spec.c | 26 ++++++++++++++++++--------
+ 1 file changed, 18 insertions(+), 8 deletions(-)
+
+diff --git a/gcc/cp/g++spec.c b/gcc/cp/g++spec.c
+index c6fc90d546d6..0bc7d4f78018 100644
+--- gcc/cp/g++spec.c
++++ gcc/cp/g++spec.c
+@@ -350,14 +350,24 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
+
+ #ifdef TARGET_AMIGA
+ {
+- extern const char *
+- amiga_m68k_prefix_func (int argc, const char ** argv);
+- char const * cxxglue = "../lib/gcc/m68k-amigaos/"
+- DEFAULT_TARGET_VERSION
+- "/cxxglue.o";
+- char const * p = amiga_m68k_prefix_func (1, &cxxglue);
+- generate_option_input_file (p, &new_decoded_options[j]);
+- ++j;
++ bool addglue = true;
++ /* do not add glue if exceptions are disabled. */
++ for (int ii = 0; ii < argc; ++ii)
++ {
++ if (decoded_options[ii].opt_index == OPT_fexceptions)
++ addglue = decoded_options[ii].opt_index;
++ }
++ if (addglue)
++ {
++ extern const char *
++ amiga_m68k_prefix_func (int argc, const char ** argv);
++ char const * cxxglue = "../lib/gcc/m68k-amigaos/"
++ DEFAULT_TARGET_VERSION
++ "/cxxglue.o";
++ char const * p = amiga_m68k_prefix_func (1, &cxxglue);
++ generate_option_input_file (p, &new_decoded_options[j]);
++ ++j;
++ }
+ }
+ #endif
+
+
+From 68afa4d4843d806f89436406aa175babaf951e33 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 11 Jul 2017 12:42:57 +0200
+Subject: [PATCH 205/303] @R enable cxxglue
+
+---
+ libgcc/Makefile.in | 4 ++--
+ libgcc/config.host | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
+index f09b39b0e85f..39f91d1567b6 100644
+--- libgcc/Makefile.in
++++ libgcc/Makefile.in
+@@ -230,7 +230,7 @@ endif
+ # Options to use when compiling libgcc2.a.
+ #
+ LIBGCC2_DEBUG_CFLAGS = -g
+-LIBGCC2_CFLAGS = -O2 $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) $(HOST_LIBGCC2_CFLAGS) \
++LIBGCC2_CFLAGS = $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) $(HOST_LIBGCC2_CFLAGS) \
+ $(LIBGCC2_DEBUG_CFLAGS) -DIN_LIBGCC2 \
+ -fbuilding-libgcc -fno-stack-protector \
+ $(INHIBIT_LIBC_CFLAGS)
+@@ -284,7 +284,7 @@ INTERNAL_CFLAGS = $(CFLAGS) $(LIBGCC2_CFLAGS) $(HOST_LIBGCC2_CFLAGS) \
+ $(INCLUDES) @set_have_cc_tls@ @set_use_emutls@
+
+ # Options to use when compiling crtbegin/end.
+-CRTSTUFF_CFLAGS = -O2 $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \
++CRTSTUFF_CFLAGS = $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) \
+ $(NO_PIE_CFLAGS) -finhibit-size-directive -fno-inline -fno-exceptions \
+ -fno-zero-initialized-in-bss -fno-toplevel-reorder -fno-tree-vectorize \
+ -fbuilding-libgcc -fno-stack-protector $(FORCE_EXPLICIT_EH_REGISTRY) \
+diff --git a/libgcc/config.host b/libgcc/config.host
+index 1478faa2b027..0fa6eab77340 100644
+--- libgcc/config.host
++++ libgcc/config.host
+@@ -817,7 +817,7 @@ m32rle-*-linux*)
+ tmake_file="$tmake_file m32r/t-linux t-fdpbit"
+ ;;
+ m68k-*-amiga*)
+-# tmake_file="$tmake_file m68k/t-floatlib"
++ tmake_file="$tmake_file m68k/t-cxxglue"
+ ;;
+ m68k-*-elf* | fido-*-elf)
+ tmake_file="$tmake_file m68k/t-floatlib"
+
+From 3984d072175a725d99fa7fdab7e553f8edf7d413 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 11 Jul 2017 12:47:04 +0200
+Subject: [PATCH 206/303] @R remove some hard coded -O2 flags
+
+---
+ libstdc++-v3/configure.host | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/libstdc++-v3/configure.host b/libstdc++-v3/configure.host
+index 354b1c7ead46..137e15e96d26 100644
+--- libstdc++-v3/configure.host
++++ libstdc++-v3/configure.host
+@@ -228,8 +228,7 @@ case "${host_os}" in
+ ;;
+ amiga*)
+ os_include_dir="os/newlib"
+- CXXFLAGS="${CXXFLAGS} -noixemul"
+- CPPFLAGS="${CPPFLAGS} -noixemul"
++ CFLAGS="-Os -noixemul"
+ ;;
+ bsd*)
+ # Plain BSD attempts to share FreeBSD files.
+
+From a3f9038954373027f5ff07bf1a694b90dc86bd49 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 11 Jul 2017 12:47:49 +0200
+Subject: [PATCH 207/303] @N hacked the mechanism to restore the registers
+ during excpetion handling
+
+---
+ libgcc/unwind-dw2.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++--
+ libgcc/unwind.inc | 8 ++---
+ 2 files changed, 86 insertions(+), 7 deletions(-)
+
+diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
+index 1fb6026d123f..da6e077b7b3c 100644
+--- libgcc/unwind-dw2.c
++++ libgcc/unwind-dw2.c
+@@ -260,6 +260,9 @@ _Unwind_GetCFA (struct _Unwind_Context *context)
+ }
+
+ /* Overwrite the saved value for register INDEX in CONTEXT with VAL. */
++#ifdef TARGET_AMIGA
++static int overregs[16];
++#endif
+
+ inline void
+ _Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
+@@ -271,6 +274,9 @@ _Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
+ gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
+ size = dwarf_reg_size_table[index];
+
++#ifdef TARGET_AMIGA
++ overregs[index] = val;
++#endif
+ if (_Unwind_IsExtendedContext (context) && context->by_value[index])
+ {
+ context->reg[index] = _Unwind_Get_Unwind_Context_Reg_Val (val);
+@@ -279,6 +285,9 @@ _Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
+
+ ptr = (void *) (_Unwind_Internal_Ptr) context->reg[index];
+
++ if (!ptr)
++ return;
++
+ if (size == sizeof(_Unwind_Ptr))
+ * (_Unwind_Ptr *) ptr = val;
+ else
+@@ -1612,10 +1621,10 @@ _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
+ macro because __builtin_eh_return must be invoked in the context of
+ our caller. */
+
+-#define uw_install_context(CURRENT, TARGET) \
++#define uw_install_context(CURRENT, TARGET, INDEX) \
+ do \
+ { \
+- long offset = uw_install_context_1 ((CURRENT), (TARGET)); \
++ long offset = uw_install_context_1 ((CURRENT), (TARGET), (INDEX)); \
+ void *handler = __builtin_frob_return_addr ((TARGET)->ra); \
+ _Unwind_DebugHook ((TARGET)->cfa, handler); \
+ __builtin_eh_return (offset, handler); \
+@@ -1624,7 +1633,8 @@ _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
+
+ static long
+ uw_install_context_1 (struct _Unwind_Context *current,
+- struct _Unwind_Context *target)
++ struct _Unwind_Context *target,
++ int index ATTRIBUTE_UNUSED)
+ {
+ long i;
+ _Unwind_SpTmp sp_slot;
+@@ -1659,7 +1669,76 @@ uw_install_context_1 (struct _Unwind_Context *current,
+ else if (t && c && t != c)
+ memcpy (c, t, dwarf_reg_size_table[i]);
+ }
++ }
++#ifdef __AMIGA__
++ /* SBF: evil hack to patch the values for d0/d1 into the stack location.
++ * search the movem insn and count the saved regs.
++ * Now patch the values into location.
++ * Always patch d0/d1 since override is always invoked for d0/d1.
++ * Then patch all other regs which the above code omitted.
++ */
++ /* uw_install_context_1 is called from 4 different locations - each uses an unique index.
++ * So initialization is only done once.
++ */
++ static unsigned short counts[4];
++ static unsigned short masks[4];
++
++ unsigned short count = 0;
++ unsigned short reg_mask = masks[index];
++ /* init each index once. */
++ if (!reg_mask)
++ {
++ /* get the return address.*/
++ unsigned short * sp = *(((unsigned short **)&current) - 1);
++ /* search the movem -x(a5),regs insn.*/
++ for (;;)
++ {
++ unsigned short s = *sp++;
++// printf("%04x ", s);
++ gcc_assert(s != (unsigned short)0x4e75);// hit return? ouch!
++ if (s == (unsigned short)0x4ced)
++ break;
++ }
++ reg_mask = *sp;
++ /* count saved regs */
++ for (unsigned short i = 0, m = reg_mask; i < 16; ++i)
++ {
++ if (m & 1)
++ ++count;
++ m >>= 1;
++ }
++ masks[index] = reg_mask;
++ counts[index] = count;
++ }
++ else
++ count = counts[index];
++
++ /* regs are saved below local vars -> start at current */
++ int * p = ((int *)current) - count;
++
++ for (unsigned short i = 0, m = reg_mask; i < 16; ++i)
++ {
++ if (m & 1)
++ {
++ if (i <= 1 || (!current->reg[i] && (target->reg[i] || target->by_value[i])))
++ {
++ int old = *p;
++ /* not set by the code above - set it here */
++ if (i <= 1) // use the override values for d0/d1
++ *p = overregs[i];
++ else
++ if (target->by_value[i])
++ *p = (int)target->reg[i];
++ else
++ *p = *(int*)target->reg[i];
++// printf("patch reg %d from %08lx to %08lx\n", i, old, *p);
++ }
++ ++p;
++ }
++ m >>= 1;
++ }
+
++#endif
+ /* If the current frame doesn't have a saved stack pointer, then we
+ need to rely on EH_RETURN_STACKADJ_RTX to get our target stack
+ pointer value reloaded. */
+diff --git a/libgcc/unwind.inc b/libgcc/unwind.inc
+index 7413b55e3fab..bf07725ac840 100644
+--- libgcc/unwind.inc
++++ libgcc/unwind.inc
+@@ -132,7 +132,7 @@ _Unwind_RaiseException(struct _Unwind_Exception *exc)
+ if (code != _URC_INSTALL_CONTEXT)
+ return code;
+
+- uw_install_context (&this_context, &cur_context);
++ uw_install_context (&this_context, &cur_context, 0);
+ }
+
+
+@@ -208,7 +208,7 @@ _Unwind_ForcedUnwind (struct _Unwind_Exception *exc,
+ if (code != _URC_INSTALL_CONTEXT)
+ return code;
+
+- uw_install_context (&this_context, &cur_context);
++ uw_install_context (&this_context, &cur_context, 1);
+ }
+
+
+@@ -233,7 +233,7 @@ _Unwind_Resume (struct _Unwind_Exception *exc)
+
+ gcc_assert (code == _URC_INSTALL_CONTEXT);
+
+- uw_install_context (&this_context, &cur_context);
++ uw_install_context (&this_context, &cur_context, 2);
+ }
+
+
+@@ -258,7 +258,7 @@ _Unwind_Resume_or_Rethrow (struct _Unwind_Exception *exc)
+
+ gcc_assert (code == _URC_INSTALL_CONTEXT);
+
+- uw_install_context (&this_context, &cur_context);
++ uw_install_context (&this_context, &cur_context, 3);
+ }
+
+
+
+From 1d661106336bf40c63163fcc4e30c9c46b45cf9e Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 11 Jul 2017 12:48:11 +0200
+Subject: [PATCH 208/303] @V bump version
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 58e8c652ab1b..51af5f4da01f 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170707-215619
++20170711-124202
+
+From af2b3738ed3afb31a0c1aed11cdc5e2d9db3a65b Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 11 Jul 2017 12:49:56 +0200
+Subject: [PATCH 209/303] @B fix evaluating -fno-exceptions
+
+---
+ gcc/cp/g++spec.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/cp/g++spec.c b/gcc/cp/g++spec.c
+index 0bc7d4f78018..83a5ab514c79 100644
+--- gcc/cp/g++spec.c
++++ gcc/cp/g++spec.c
+@@ -355,7 +355,7 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
+ for (int ii = 0; ii < argc; ++ii)
+ {
+ if (decoded_options[ii].opt_index == OPT_fexceptions)
+- addglue = decoded_options[ii].opt_index;
++ addglue = decoded_options[ii].value;
+ }
+ if (addglue)
+ {
+
+From 11b4ecb7269e55ca24a184e558883aeb5fe33342 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 12 Jul 2017 07:24:02 +0200
+Subject: [PATCH 210/303] @B fix merge ...
+
+---
+ libgcc/unwind-dw2.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
+index da6e077b7b3c..7bf0e4236f64 100644
+--- libgcc/unwind-dw2.c
++++ libgcc/unwind-dw2.c
+@@ -1669,7 +1669,6 @@ uw_install_context_1 (struct _Unwind_Context *current,
+ else if (t && c && t != c)
+ memcpy (c, t, dwarf_reg_size_table[i]);
+ }
+- }
+ #ifdef __AMIGA__
+ /* SBF: evil hack to patch the values for d0/d1 into the stack location.
+ * search the movem insn and count the saved regs.
+
+From c760f9bdfda61e158d5d71b44d9163f7802d0314 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 12 Jul 2017 09:12:56 +0200
+Subject: [PATCH 211/303] @B fix libstdc++ config
+
+---
+ libstdc++-v3/configure.host | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/libstdc++-v3/configure.host b/libstdc++-v3/configure.host
+index 137e15e96d26..fde4a72bd31b 100644
+--- libstdc++-v3/configure.host
++++ libstdc++-v3/configure.host
+@@ -229,6 +229,7 @@ case "${host_os}" in
+ amiga*)
+ os_include_dir="os/newlib"
+ CFLAGS="-Os -noixemul"
++ CPPFLAGS="-Os -noixemul"
+ ;;
+ bsd*)
+ # Plain BSD attempts to share FreeBSD files.
+
+From bd065307745a5bbf8c56e72d94e291e595103897 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 12 Jul 2017 12:08:05 +0200
+Subject: [PATCH 212/303] change host pattern from m68k-*-amiga to m68k*-amiga
+
+---
+ libgcc/config.host | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/libgcc/config.host b/libgcc/config.host
+index 0fa6eab77340..8e4fb7942f79 100644
+--- libgcc/config.host
++++ libgcc/config.host
+@@ -816,7 +816,7 @@ m32r-*-linux*)
+ m32rle-*-linux*)
+ tmake_file="$tmake_file m32r/t-linux t-fdpbit"
+ ;;
+-m68k-*-amiga*)
++m68k*-amiga*)
+ tmake_file="$tmake_file m68k/t-cxxglue"
+ ;;
+ m68k-*-elf* | fido-*-elf)
+
+From 17dc596a0d8a232ae647216f27d707010c3e836e Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 12 Jul 2017 14:07:28 +0200
+Subject: [PATCH 213/303] fix t-glue makefile name
+
+---
+ libgcc/config.host | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/libgcc/config.host b/libgcc/config.host
+index 8e4fb7942f79..5de7abdb8a95 100644
+--- libgcc/config.host
++++ libgcc/config.host
+@@ -816,8 +816,8 @@ m32r-*-linux*)
+ m32rle-*-linux*)
+ tmake_file="$tmake_file m32r/t-linux t-fdpbit"
+ ;;
+-m68k*-amiga*)
+- tmake_file="$tmake_file m68k/t-cxxglue"
++m68k-*-amiga*)
++ tmake_file="$tmake_file m68k/t-glue"
+ ;;
+ m68k-*-elf* | fido-*-elf)
+ tmake_file="$tmake_file m68k/t-floatlib"
+
+From cfa7b74b520032da16a32425a6d206cba92d0feb Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 20 Aug 2017 21:40:08 +0200
+Subject: [PATCH 214/303] fix #1: fix inc/erase with iterator
+
+---
+ gcc/bbb-opts.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 365eec1c7280..99785cf5d6ad 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -3608,7 +3608,7 @@ track_regs ()
+ j != reg2slot.end () && j->first == k->first;)
+ {
+ values[j->second] = 0;
+- reg2slot.erase (j++);
++ j = reg2slot.erase (j);
+ }
+ }
+ }
+@@ -3649,7 +3649,7 @@ track_regs ()
+ j != reg2slot.end () && j->first == k->first;)
+ {
+ values[j->second] = 0;
+- reg2slot.erase (j++);
++ j = reg2slot.erase (j);
+ }
+ }
+
+@@ -3670,7 +3670,7 @@ track_regs ()
+ j != reg2slot.end () && j->first == k->first;)
+ {
+ values[j->second] = 0;
+- reg2slot.erase (j++);
++ j = reg2slot.erase (j);
+ }
+ }
+
+@@ -3886,9 +3886,9 @@ opt_absolute (void)
+ bool k_src = kk.is_src_mem () && (kk.has_src_addr () || kk.get_src_symbol ()) && !kk.has_src_memreg ()
+ && kk.get_src_symbol () == with_symbol;
+ if (k_dst && kk.get_dst_addr () - base > 0x7ffc)
+- found.erase (k++);
++ k = found.erase (k);
+ else if (k_src && kk.get_src_mem_addr () - base > 0x7ffc)
+- found.erase (k++);
++ k = found.erase (k);
+ else
+ ++k;
+ }
+
+From 13bdc411c4eb3fcec280affc02b38e8e7b29e7d4 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 21 Aug 2017 17:49:51 +0200
+Subject: [PATCH 215/303] fix printing baserel insns, avoid combines resulting
+ in 'not pic_reg'
+
+---
+ gcc/config/m68k/amigaos.c | 32 ++++++++++++++++++++++++++++++++
+ gcc/config/m68k/amigaos.h | 5 +++++
+ gcc/config/m68k/m68k.c | 2 +-
+ 3 files changed, 38 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index dc2f2ac74369..6aee22fa3720 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -885,3 +885,35 @@ amigaos_static_chain_rtx (const_tree decl, bool incoming ATTRIBUTE_UNUSED)
+ return 0;
+ }
+
++/*
++ * decline src like:
++(plus:SI (reg/f:SI 0 d0 [210])
++ (const:SI (minus:SI (not:SI (reg:SI 12 a4))
++ *
++ */
++bool
++amigaos_legitimate_combined_insn (rtx_insn * insn)
++{
++ rtx set = single_set(insn);
++ if (!set)
++ return true;
++
++ rtx x = SET_SRC(set);
++ if (GET_CODE(x) != PLUS)
++ return true;
++
++ x = XEXP(x, 1);
++ if (GET_CODE(x) != CONST)
++ return true;
++
++ x = XEXP(x, 0);
++ if (GET_CODE(x) != MINUS)
++ return true;
++
++ x = XEXP(x, 0);
++ if (GET_CODE(x) != NOT)
++ return true;
++
++ x = XEXP(x, 0);
++ return !REG_P(x);
++}
+diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h
+index c564c3f2db67..688f04e37ebb 100644
+--- gcc/config/m68k/amigaos.h
++++ gcc/config/m68k/amigaos.h
+@@ -477,3 +477,8 @@ amigaos_struct_value_rtx(tree fntype,
+ rtx
+ amigaos_static_chain_rtx(const_tree fntype,
+ bool incoming ATTRIBUTE_UNUSED);
++
++#undef TARGET_LEGITIMATE_COMBINED_INSN
++#define TARGET_LEGITIMATE_COMBINED_INSN amigaos_legitimate_combined_insn
++bool
++amigaos_legitimate_combined_insn (rtx_insn *insn ATTRIBUTE_UNUSED);
+diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
+index d123cc065c18..ed9b76caf11d 100644
+--- gcc/config/m68k/m68k.c
++++ gcc/config/m68k/m68k.c
+@@ -4626,7 +4626,7 @@ print_operand (FILE *file, rtx op, int letter)
+ /* Use `print_operand_address' instead of `output_addr_const'
+ to ensure that we print relevant PIC stuff. */
+ asm_fprintf (file, "%I");
+- if (TARGET_PCREL
++ if ((TARGET_PCREL || flag_pic > 2)
+ && (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST))
+ print_operand_address (file, op);
+ else
+
+From dd13371d6f4ca2e66804a589b50d2bca47d58653 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 21 Aug 2017 20:27:22 +0200
+Subject: [PATCH 216/303] avoid invalid addressing modes with baserel modes
+
+---
+ gcc/config/m68k/m68k.md | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
+index d5ab0cfab8c8..c9ea341789f4 100644
+--- gcc/config/m68k/m68k.md
++++ gcc/config/m68k/m68k.md
+@@ -2468,7 +2468,7 @@
+ (define_insn "*addsi3_internal"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=m,?a,?a,d,a")
+ (plus:SI (match_operand:SI 1 "general_operand" "%0,a,rJK,0,0")
+- (match_operand:SI 2 "general_src_operand" "dIKLT,rJK,a,mSrIKLT,mSrIKLs")))]
++ (match_operand:SI 2 "general_src_operand" "dIKLT,rJK,a,mSrIKLt,mSrIKLt")))]
+
+
+ "! TARGET_COLDFIRE"
+
+From 7edabb7a5a3018fd8b1f410f38a31122cc0ea493 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 21 Aug 2017 20:33:59 +0200
+Subject: [PATCH 217/303] bump datestamp
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 51af5f4da01f..d77b05782e7b 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170711-124202
++20170821-203326
+
+From 3142cd34592cdaf86c3fab9de2c674225257df8b Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 31 Aug 2017 16:14:24 +0200
+Subject: [PATCH 218/303] #2 treat CLOBBERed regs as defined regs
+
+---
+ gcc/bbb-opts.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 99785cf5d6ad..77537a73a873 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -1003,6 +1003,9 @@ insn_info::scan_rtx (rtx x)
+ def |= d;
+ }
+ }
++
++ if (code == CLOBBER)
++ def |= use;
+ }
+
+ void
+
+From 821e16347528355a29fdcfd521f7cdb26414a67f Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 31 Aug 2017 16:18:10 +0200
+Subject: [PATCH 219/303] also use libm020 with mcpu=68030 and higher
+
+---
+ gcc/config/m68k/m68kamigaos.h | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h
+index beac496ab148..7dc0e57f5cdc 100644
+--- gcc/config/m68k/m68kamigaos.h
++++ gcc/config/m68k/m68kamigaos.h
+@@ -540,6 +540,9 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ "%{resident32:-m amiga_bss -amiga-datadata-reloc -fl libb32 %{noixemul:-fl libnix} %{mcrt=nix*:-fl libnix}} " \
+ "%{g:-amiga-debug-hunk} " \
+ "%{mcpu=68020:-fl libm020} " \
++ "%{mcpu=68030:-fl libm020} " \
++ "%{mcpu=68040:-fl libm020} " \
++ "%{mcpu=68060:-fl libm020} " \
+ "%{m68020:-fl libm020} " \
+ "%{mc68020:-fl libm020} " \
+ "%{m68030:-fl libm020} " \
+
+From 8529c8e37e017866c4d062006a00219fd4977381 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 31 Aug 2017 16:25:52 +0200
+Subject: [PATCH 220/303] bump DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index d77b05782e7b..0dfee2790f53 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170821-203326
++20170831-161819
+
+From 592ee5156864548a6d918a34001781a5a73eb51b Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 11 Oct 2017 23:39:40 +0200
+Subject: [PATCH 221/303] split fpgnulib into files per function
+
+---
+ libgcc/config.host | 3 ++-
+ libgcc/config/m68k/fpgnulib.c | 22 +++++++++++++++++
+ libgcc/config/m68k/t-floatlib | 57 ++++++++++++++++++++++++++++++++++++++-----
+ 3 files changed, 75 insertions(+), 7 deletions(-)
+
+diff --git a/libgcc/config.host b/libgcc/config.host
+index 5de7abdb8a95..c36e829a5025 100644
+--- libgcc/config.host
++++ libgcc/config.host
+@@ -817,7 +817,8 @@ m32rle-*-linux*)
+ tmake_file="$tmake_file m32r/t-linux t-fdpbit"
+ ;;
+ m68k-*-amiga*)
+- tmake_file="$tmake_file m68k/t-glue"
++ tmake_file="$tmake_file m68k/t-glue m68k/t-floatlib soft-fp"
++# tmake_file="$tmake_file m68k/t-glue soft-fp"
+ ;;
+ m68k-*-elf* | fido-*-elf)
+ tmake_file="$tmake_file m68k/t-floatlib"
+diff --git a/libgcc/config/m68k/fpgnulib.c b/libgcc/config/m68k/fpgnulib.c
+index fe41edf26aa0..9dcd5ea20397 100644
+--- libgcc/config/m68k/fpgnulib.c
++++ libgcc/config/m68k/fpgnulib.c
+@@ -105,6 +105,7 @@ union long_double_long
+
+ #ifndef EXTFLOAT
+
++#ifdef __UNORDSF2
+ int
+ __unordsf2(float a, float b)
+ {
+@@ -118,7 +119,9 @@ __unordsf2(float a, float b)
+ return 1;
+ return 0;
+ }
++#endif
+
++#ifdef __UNORDDF2
+ int
+ __unorddf2(double a, double b)
+ {
+@@ -134,7 +137,9 @@ __unorddf2(double a, double b)
+ return 1;
+ return 0;
+ }
++#endif
+
++#ifdef __FLOATUNSIDF
+ /* convert unsigned int to double */
+ double
+ __floatunsidf (unsigned long a1)
+@@ -167,7 +172,9 @@ __floatunsidf (unsigned long a1)
+
+ return dl.d;
+ }
++#endif
+
++#ifdef __FLOATSIDF
+ /* convert int to double */
+ double
+ __floatsidf (long a1)
+@@ -213,7 +220,9 @@ __floatsidf (long a1)
+
+ return dl.d;
+ }
++#endif
+
++#ifdef __FLOATUNSISF
+ /* convert unsigned int to float */
+ float
+ __floatunsisf (unsigned long l)
+@@ -221,7 +230,10 @@ __floatunsisf (unsigned long l)
+ double foo = __floatunsidf (l);
+ return foo;
+ }
++#endif
+
++
++#ifdef __FLOATSISF
+ /* convert int to float */
+ float
+ __floatsisf (long l)
+@@ -229,7 +241,10 @@ __floatsisf (long l)
+ double foo = __floatsidf (l);
+ return foo;
+ }
++#endif
++
+
++#ifdef __EXTENDSFDF2
+ /* convert float to double */
+ double
+ __extendsfdf2 (float a1)
+@@ -268,7 +283,9 @@ __extendsfdf2 (float a1)
+
+ return dl.d;
+ }
++#endif
+
++#ifdef __TRUNCDFSF2
+ /* convert double to float */
+ float
+ __truncdfsf2 (double a1)
+@@ -336,7 +353,9 @@ __truncdfsf2 (double a1)
+ fl.l = PACK (SIGND (dl1), exp, mant);
+ return (fl.f);
+ }
++#endif
+
++#ifdef __FIXDFSI
+ /* convert double to int */
+ long
+ __fixdfsi (double a1)
+@@ -368,7 +387,9 @@ __fixdfsi (double a1)
+
+ return (SIGND (dl1) ? -l : l);
+ }
++#endif
+
++#ifdef __FIXSFSI
+ /* convert float to int */
+ long
+ __fixsfsi (float a1)
+@@ -376,6 +397,7 @@ __fixsfsi (float a1)
+ double foo = a1;
+ return __fixdfsi (foo);
+ }
++#endif
+
+ #else /* EXTFLOAT */
+
+diff --git a/libgcc/config/m68k/t-floatlib b/libgcc/config/m68k/t-floatlib
+index 1ee8782d9fd2..42f6cf97ef48 100644
+--- libgcc/config/m68k/t-floatlib
++++ libgcc/config/m68k/t-floatlib
+@@ -1,10 +1,55 @@
+-LIB1ASMSRC = m68k/lb1sf68.S
+-LIB1ASMFUNCS = _mulsi3 _udivsi3 _divsi3 _umodsi3 _modsi3 \
+- _double _float _floatex \
+- _eqdf2 _nedf2 _gtdf2 _gedf2 _ltdf2 _ledf2 \
+- _eqsf2 _nesf2 _gtsf2 _gesf2 _ltsf2 _lesf2
++#
++#LIB1ASMSRC = m68k/lb1sf68.S
++#LIB1ASMFUNCS = _mulsi3 _udivsi3 _divsi3 _umodsi3 _modsi3 \
++# _double _float _floatex \
++# _eqdf2 _nedf2 _gtdf2 _gedf2 _ltdf2 _ledf2 \
++# _eqsf2 _nesf2 _gtsf2 _gesf2 _ltsf2 _lesf2
++#
+
+-LIB2ADD = $(srcdir)/config/m68k/fpgnulib.c xfgnulib.c
++LIB2ADD = xfgnulib.c xfgnulib__unordsf2.c xfgnulib__unorddf2.c \
++ xfgnulib__floatunsidf.c xfgnulib__floatsidf.c xfgnulib__floatunsisf.c \
++ xfgnulib__floatsisf.c xfgnulib__extendsfdf2.c xfgnulib__truncdfsf2.c \
++ xfgnulib__fixdfsi.c xfgnulib__fixsfsi.c
++
++xfgnulib__unordsf2.c: $(srcdir)/config/m68k/fpgnulib.c
++ echo '#define __UNORDSF2' > xfgnulib__unordsf2.c
++ cat $< >> xfgnulib__unordsf2.c
++
++xfgnulib__unorddf2.c: $(srcdir)/config/m68k/fpgnulib.c
++ echo '#define __UNORDDF2' > xfgnulib__unorddf2.c
++ cat $< >> xfgnulib__unorddf2.c
++
++xfgnulib__floatunsidf.c: $(srcdir)/config/m68k/fpgnulib.c
++ echo '#define __FLOATUNSIDF' > xfgnulib__floatunsidf.c
++ cat $< >> xfgnulib__floatunsidf.c
++
++xfgnulib__floatsidf.c: $(srcdir)/config/m68k/fpgnulib.c
++ echo '#define __FLOATSIDF' > xfgnulib__floatsidf.c
++ cat $< >> xfgnulib__floatsidf.c
++
++xfgnulib__floatunsisf.c: $(srcdir)/config/m68k/fpgnulib.c
++ echo '#define __FLOATUNSISF' > xfgnulib__floatunsisf.c
++ cat $< >> xfgnulib__floatunsisf.c
++
++xfgnulib__floatsisf.c: $(srcdir)/config/m68k/fpgnulib.c
++ echo '#define __FLOATSISF' > xfgnulib__floatsisf.c
++ cat $< >> xfgnulib__floatsisf.c
++
++xfgnulib__extendsfdf2.c: $(srcdir)/config/m68k/fpgnulib.c
++ echo '#define __EXTENDSFDF2' > xfgnulib__extendsfdf2.c
++ cat $< >> xfgnulib__extendsfdf2.c
++
++xfgnulib__truncdfsf2.c: $(srcdir)/config/m68k/fpgnulib.c
++ echo '#define __TRUNCDFSF2' > xfgnulib__truncdfsf2.c
++ cat $< >> xfgnulib__truncdfsf2.c
++
++xfgnulib__fixdfsi.c: $(srcdir)/config/m68k/fpgnulib.c
++ echo '#define __FIXDFSI' > xfgnulib__fixdfsi.c
++ cat $< >> xfgnulib__fixdfsi.c
++
++xfgnulib__fixsfsi.c: $(srcdir)/config/m68k/fpgnulib.c
++ echo '#define __FIXSFSI' > xfgnulib__fixsfsi.c
++ cat $< >> xfgnulib__fixsfsi.c
+
+ xfgnulib.c: $(srcdir)/config/m68k/fpgnulib.c
+ echo '#define EXTFLOAT' > xfgnulib.c
+
+From cce4b48ca8802f0c0b1ee929810a845a18285902 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 11 Oct 2017 23:40:39 +0200
+Subject: [PATCH 222/303] fix usage of return val registers for library
+ functions -> always tell the return reg.
+
+---
+ gcc/DATESTAMP | 2 +-
+ gcc/bbb-opts.c | 2 +-
+ gcc/config/m68k/amigaos.c | 4 ++--
+ 3 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 0dfee2790f53..c4335f1aad48 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20170831-161819
++20171011-233828
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 77537a73a873..fe7cd79b5c7b 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -926,7 +926,7 @@ insn_info::scan ()
+ rtx op, reg;
+
+ if (GET_CODE (op = XEXP (link, 0)) == USE && REG_P(reg = XEXP (op, 0)))
+- for (unsigned r = REGNO(reg); r <= END_REGNO (reg); ++r)
++ for (unsigned r = REGNO(reg); r < END_REGNO (reg); ++r)
+ mark_myuse (r);
+ }
+ /* mark scratch registers. */
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index 6aee22fa3720..53e01499341d 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -848,10 +848,10 @@ read_only_operand (rtx operand)
+ rtx
+ amigaos_struct_value_rtx (tree fntype, int incoming ATTRIBUTE_UNUSED)
+ {
+- if (fntype && aggregate_value_p (TREE_TYPE(fntype), fntype))
++// if (fntype && aggregate_value_p (TREE_TYPE(fntype), fntype))
+ return gen_rtx_REG (Pmode, M68K_STRUCT_VALUE_REGNUM);
+
+- return 0;
++// return 0;
+ }
+
+ rtx
+
+From aea9ac0b4d8f6261006ed68ea1bb21d0f6fe57f8 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 13 Oct 2017 22:02:17 +0200
+Subject: [PATCH 223/303] further spltting of fpgnulib
+
+---
+ libgcc/config/m68k/fpgnulib.c | 69 +++++++++++++++-------------
+ libgcc/config/m68k/t-floatlib | 102 ++++++++++++++++++++++--------------------
+ 2 files changed, 91 insertions(+), 80 deletions(-)
+
+diff --git a/libgcc/config/m68k/fpgnulib.c b/libgcc/config/m68k/fpgnulib.c
+index 9dcd5ea20397..90926104d8fd 100644
+--- libgcc/config/m68k/fpgnulib.c
++++ libgcc/config/m68k/fpgnulib.c
+@@ -418,6 +418,8 @@ float __truncdfsf2 (double);
+ long __fixdfsi (double);
+ long __fixsfsi (float);
+
++#if !defined(EXTFLOATCMP)
++
+ int
+ __unordxf2(long double a, long double b)
+ {
+@@ -467,38 +469,6 @@ __extenddfxf2 (double d)
+ return ldl.ld;
+ }
+
+-/* convert long double to double */
+-double
+-__truncxfdf2 (long double ld)
+-{
+- register long exp;
+- register union double_long dl;
+- register union long_double_long ldl;
+-
+- ldl.ld = ld;
+- /*printf ("xfdf in: %s\n", dumpxf (ld));*/
+-
+- dl.l.upper = SIGNX (ldl);
+- if ((ldl.l.upper & ~SIGNBIT) == 0 && !ldl.l.middle && !ldl.l.lower)
+- {
+- dl.l.lower = 0;
+- return dl.d;
+- }
+-
+- exp = EXPX (ldl) - EXCESSX + EXCESSD;
+- /* ??? quick and dirty: keep `exp' sane */
+- if (exp >= EXPDMASK)
+- exp = EXPDMASK - 1;
+- dl.l.upper |= exp << (32 - (EXPDBITS + 1));
+- /* +1-1: add one for sign bit, but take one off for explicit-integer-bit */
+- dl.l.upper |= (ldl.l.middle & MANTXMASK) >> (EXPDBITS + 1 - 1);
+- dl.l.lower = (ldl.l.middle & MANTXMASK) << (32 - (EXPDBITS + 1 - 1));
+- dl.l.lower |= ldl.l.lower >> (EXPDBITS + 1 - 1);
+-
+- /*printf ("xfdf out: %g\n", dl.d);*/
+- return dl.d;
+-}
+-
+ /* convert a float to a long double */
+ long double
+ __extendsfxf2 (float f)
+@@ -571,6 +541,8 @@ __negxf2 (long double x1)
+ return - (double) x1;
+ }
+
++#else
++
+ long
+ __cmpxf2 (long double x1, long double x2)
+ {
+@@ -613,5 +585,38 @@ __gexf2 (long double x1, long double x2)
+ return __cmpdf2 ((double) x1, (double) x2);
+ }
+
++/* convert long double to double */
++double
++__truncxfdf2 (long double ld)
++{
++ register long exp;
++ register union double_long dl;
++ register union long_double_long ldl;
++
++ ldl.ld = ld;
++ /*printf ("xfdf in: %s\n", dumpxf (ld));*/
++
++ dl.l.upper = SIGNX (ldl);
++ if ((ldl.l.upper & ~SIGNBIT) == 0 && !ldl.l.middle && !ldl.l.lower)
++ {
++ dl.l.lower = 0;
++ return dl.d;
++ }
++
++ exp = EXPX (ldl) - EXCESSX + EXCESSD;
++ /* ??? quick and dirty: keep `exp' sane */
++ if (exp >= EXPDMASK)
++ exp = EXPDMASK - 1;
++ dl.l.upper |= exp << (32 - (EXPDBITS + 1));
++ /* +1-1: add one for sign bit, but take one off for explicit-integer-bit */
++ dl.l.upper |= (ldl.l.middle & MANTXMASK) >> (EXPDBITS + 1 - 1);
++ dl.l.lower = (ldl.l.middle & MANTXMASK) << (32 - (EXPDBITS + 1 - 1));
++ dl.l.lower |= ldl.l.lower >> (EXPDBITS + 1 - 1);
++
++ /*printf ("xfdf out: %g\n", dl.d);*/
++ return dl.d;
++}
++#endif /* EXTFLOATCMP */
++
+ #endif /* !__mcoldfire__ */
+ #endif /* EXTFLOAT */
+diff --git a/libgcc/config/m68k/t-floatlib b/libgcc/config/m68k/t-floatlib
+index 42f6cf97ef48..2365433a59b3 100644
+--- libgcc/config/m68k/t-floatlib
++++ libgcc/config/m68k/t-floatlib
+@@ -6,51 +6,57 @@
+ # _eqsf2 _nesf2 _gtsf2 _gesf2 _ltsf2 _lesf2
+ #
+
+-LIB2ADD = xfgnulib.c xfgnulib__unordsf2.c xfgnulib__unorddf2.c \
+- xfgnulib__floatunsidf.c xfgnulib__floatsidf.c xfgnulib__floatunsisf.c \
+- xfgnulib__floatsisf.c xfgnulib__extendsfdf2.c xfgnulib__truncdfsf2.c \
+- xfgnulib__fixdfsi.c xfgnulib__fixsfsi.c
+-
+-xfgnulib__unordsf2.c: $(srcdir)/config/m68k/fpgnulib.c
+- echo '#define __UNORDSF2' > xfgnulib__unordsf2.c
+- cat $< >> xfgnulib__unordsf2.c
+-
+-xfgnulib__unorddf2.c: $(srcdir)/config/m68k/fpgnulib.c
+- echo '#define __UNORDDF2' > xfgnulib__unorddf2.c
+- cat $< >> xfgnulib__unorddf2.c
+-
+-xfgnulib__floatunsidf.c: $(srcdir)/config/m68k/fpgnulib.c
+- echo '#define __FLOATUNSIDF' > xfgnulib__floatunsidf.c
+- cat $< >> xfgnulib__floatunsidf.c
+-
+-xfgnulib__floatsidf.c: $(srcdir)/config/m68k/fpgnulib.c
+- echo '#define __FLOATSIDF' > xfgnulib__floatsidf.c
+- cat $< >> xfgnulib__floatsidf.c
+-
+-xfgnulib__floatunsisf.c: $(srcdir)/config/m68k/fpgnulib.c
+- echo '#define __FLOATUNSISF' > xfgnulib__floatunsisf.c
+- cat $< >> xfgnulib__floatunsisf.c
+-
+-xfgnulib__floatsisf.c: $(srcdir)/config/m68k/fpgnulib.c
+- echo '#define __FLOATSISF' > xfgnulib__floatsisf.c
+- cat $< >> xfgnulib__floatsisf.c
+-
+-xfgnulib__extendsfdf2.c: $(srcdir)/config/m68k/fpgnulib.c
+- echo '#define __EXTENDSFDF2' > xfgnulib__extendsfdf2.c
+- cat $< >> xfgnulib__extendsfdf2.c
+-
+-xfgnulib__truncdfsf2.c: $(srcdir)/config/m68k/fpgnulib.c
+- echo '#define __TRUNCDFSF2' > xfgnulib__truncdfsf2.c
+- cat $< >> xfgnulib__truncdfsf2.c
+-
+-xfgnulib__fixdfsi.c: $(srcdir)/config/m68k/fpgnulib.c
+- echo '#define __FIXDFSI' > xfgnulib__fixdfsi.c
+- cat $< >> xfgnulib__fixdfsi.c
+-
+-xfgnulib__fixsfsi.c: $(srcdir)/config/m68k/fpgnulib.c
+- echo '#define __FIXSFSI' > xfgnulib__fixsfsi.c
+- cat $< >> xfgnulib__fixsfsi.c
+-
+-xfgnulib.c: $(srcdir)/config/m68k/fpgnulib.c
+- echo '#define EXTFLOAT' > xfgnulib.c
+- cat $< >> xfgnulib.c
++LIB2ADD = xfpgnulib.c xfpgnulib__unordsf2.c xfpgnulib__unorddf2.c \
++ xfpgnulib__floatunsidf.c xfpgnulib__floatsidf.c xfpgnulib__floatunsisf.c \
++ xfpgnulib__floatsisf.c xfpgnulib__extendsfdf2.c xfpgnulib__truncdfsf2.c \
++ xfpgnulib__fixdfsi.c xfpgnulib__fixsfsi.c xfpgnulib__cmpxf2.c
++
++xfpgnulib__unordsf2.c: $(srcdir)/config/m68k/fpgnulib.c
++ echo '#define __UNORDSF2' > xfpgnulib__unordsf2.c
++ cat $< >> xfpgnulib__unordsf2.c
++
++xfpgnulib__unorddf2.c: $(srcdir)/config/m68k/fpgnulib.c
++ echo '#define __UNORDDF2' > xfpgnulib__unorddf2.c
++ cat $< >> xfpgnulib__unorddf2.c
++
++xfpgnulib__floatunsidf.c: $(srcdir)/config/m68k/fpgnulib.c
++ echo '#define __FLOATUNSIDF' > xfpgnulib__floatunsidf.c
++ cat $< >> xfpgnulib__floatunsidf.c
++
++xfpgnulib__floatsidf.c: $(srcdir)/config/m68k/fpgnulib.c
++ echo '#define __FLOATSIDF' > xfpgnulib__floatsidf.c
++ cat $< >> xfpgnulib__floatsidf.c
++
++xfpgnulib__floatunsisf.c: $(srcdir)/config/m68k/fpgnulib.c
++ echo '#define __FLOATUNSISF' > xfpgnulib__floatunsisf.c
++ cat $< >> xfpgnulib__floatunsisf.c
++
++xfpgnulib__floatsisf.c: $(srcdir)/config/m68k/fpgnulib.c
++ echo '#define __FLOATSISF' > xfpgnulib__floatsisf.c
++ cat $< >> xfpgnulib__floatsisf.c
++
++xfpgnulib__extendsfdf2.c: $(srcdir)/config/m68k/fpgnulib.c
++ echo '#define __EXTENDSFDF2' > xfpgnulib__extendsfdf2.c
++ cat $< >> xfpgnulib__extendsfdf2.c
++
++xfpgnulib__truncdfsf2.c: $(srcdir)/config/m68k/fpgnulib.c
++ echo '#define __TRUNCDFSF2' > xfpgnulib__truncdfsf2.c
++ cat $< >> xfpgnulib__truncdfsf2.c
++
++xfpgnulib__fixdfsi.c: $(srcdir)/config/m68k/fpgnulib.c
++ echo '#define __FIXDFSI' > xfpgnulib__fixdfsi.c
++ cat $< >> xfpgnulib__fixdfsi.c
++
++xfpgnulib__fixsfsi.c: $(srcdir)/config/m68k/fpgnulib.c
++ echo '#define __FIXSFSI' > xfpgnulib__fixsfsi.c
++ cat $< >> xfpgnulib__fixsfsi.c
++
++xfpgnulib.c: $(srcdir)/config/m68k/fpgnulib.c
++ echo '#define EXTFLOAT' > xfpgnulib.c
++ cat $< >> xfpgnulib.c
++
++xfpgnulib__cmpxf2.c: $(srcdir)/config/m68k/fpgnulib.c
++ echo '#define EXTFLOAT' > xfpgnulib__cmpxf2.c
++ echo '#define EXTFLOATCMP' >> xfpgnulib__cmpxf2.c
++ cat $< >> xfpgnulib__cmpxf2.c
++
+\ No newline at end of file
+
+From 97a50aa76b592060171013c4a00ac472d8711580 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 18 Oct 2017 19:45:35 +0200
+Subject: [PATCH 224/303] eliminating redundant loads (move.l reg,reg) is
+ checking that the source value is still known
+
+---
+ gcc/bbb-opts.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index fe7cd79b5c7b..6e257b22266a 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -3755,11 +3755,16 @@ opt_elim_dead_assign (unsigned blocked_regno)
+ rtx cached_value = ii.get_track_var ()->get_values ()[ii.get_dst_regno ()];
+ rtx cached_value2 = 0;
+ if (cached_value && REG_P(cached_value) && REGNO(cached_value) < FIRST_PSEUDO_REGISTER)
+- cached_value2 = ii.get_track_var ()->get_values ()[REGNO(cached_value)];
++ {
++ cached_value2 = ii.get_track_var ()->get_values ()[REGNO(cached_value)];
++ if (!cached_value2) // no value for the reg -> reg is invalid too
++ cached_value = 0;
++ }
+ if (cached_value
+ && (rtx_equal_p (cached_value, SET_SRC(set))
+ || (cached_value2 && rtx_equal_p (cached_value2, SET_SRC(set)))))
+ {
++// fprintf(stderr, "cached_value: "); debug_rtx(cached_value);
+ log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]);
+ SET_INSN_DELETED(insn);
+ ++change_count;
+
+From b9e0de6883c5bcf3c58828453cc601b889a07516 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 18 Oct 2017 19:47:25 +0200
+Subject: [PATCH 225/303] bump DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index c4335f1aad48..c95c776f3dcf 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20171011-233828
++20171018-194704
+
+From 068a438a7b99afeed45bb95c08dd38ea94f0280a Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sat, 11 Nov 2017 15:01:03 +0100
+Subject: [PATCH 226/303] improved insn checking and auto inc
+
+---
+ gcc/bbb-opts.c | 458 ++++++++++++++++++++++++++++++++++-----------------------
+ 1 file changed, 275 insertions(+), 183 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 6e257b22266a..c6aaa4dcb476 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -53,6 +53,9 @@
+ */
+
+ #include "config.h"
++#define INCLUDE_VECTOR
++#define INCLUDE_SET
++#define INCLUDE_MAP
+ #include "system.h"
+ #include "coretypes.h"
+ #include "backend.h"
+@@ -67,11 +70,6 @@
+ #include "tree-pass.h"
+ #include "conditions.h"
+ #include "langhooks.h"
+-#include <vector>
+-#include <set>
+-#include <map>
+-
+-static int xx = 0;
+
+ int be_very_verbose;
+ bool be_verbose;
+@@ -274,6 +272,9 @@ class insn_info
+ void
+ absolute2base (unsigned regno, unsigned base, rtx with_symbol);
+
++ rtx
++ make_absolute2base (unsigned regno, unsigned base, rtx with_symbol, bool apply);
++
+ inline bool
+ is_compare () const
+ {
+@@ -776,7 +777,7 @@ class insn_info
+ void
+ scan_rtx (rtx);
+
+- void
++ bool
+ make_post_inc (int regno);
+
+ void
+@@ -822,14 +823,16 @@ class insn_info
+ a5_to_a7 (rtx a7);
+ };
+
+-void
++bool
+ insn_info::make_post_inc (int regno)
+ {
++ rtx pattern = PATTERN(insn);
++ rtx_insn * new_insn = make_insn_raw(pattern);
++
+ // convert into POST_INC
+-// debug_rtx (insn);
+- rtx set0 = single_set (insn);
++ rtx set0 = single_set (new_insn);
+ rtx set = set0;
+- SET_INSN_DELETED(insn);
++
+ if (is_compare ())
+ set = SET_SRC(set);
+ rtx mem = get_dst_mem_regno () == regno ? SET_DEST(set) : SET_SRC(set);
+@@ -837,21 +840,60 @@ insn_info::make_post_inc (int regno)
+ mem = XEXP(mem, 1);
+
+ rtx reg = XEXP(mem, 0);
++
+ XEXP(mem, 0) = gen_rtx_POST_INC(SImode, reg);
+
++ if (insn_invalid_p (new_insn, 0))
++ {
++ XEXP(mem, 0) = reg;
++ insn_invalid_p (insn, 0);
++ return 0;
++ }
++
++ SET_INSN_DELETED(insn);
+ (get_dst_mem_regno () == regno ? dst_autoinc : src_autoinc) = GET_MODE_SIZE(mode);
+- insn = emit_insn_after (set0, insn);
+-// debug_rtx (insn);
++ insn = emit_insn_after (PATTERN(new_insn), insn);
++ insn_invalid_p(insn, 0);
++
++ return 1;
++}
++
++static rtx
++add_clobbers (rtx_insn * oldinsn)
++{
++ rtx pattern = PATTERN (oldinsn);
++ if (GET_CODE(pattern) != PARALLEL)
++ return pattern;
++
++ int num_clobbers = 0;
++ for (int j = XVECLEN (pattern, 0) - 1; j >= 0; j--)
++ {
++ rtx x = XVECEXP(pattern, 0, j);
++ if (GET_CODE(x) == CLOBBER)
++ ++num_clobbers;
++ }
++
++ if (!num_clobbers)
++ return pattern;
++
++ rtx newpat = gen_rtx_PARALLEL(VOIDmode, rtvec_alloc (num_clobbers + 1));
++ for (int j = XVECLEN (pattern, 0) - 1; j >= 0; j--)
++ {
++ rtx x = XVECEXP(pattern, 0, j);
++ if (GET_CODE(x) == CLOBBER)
++ XVECEXP(newpat, 0, num_clobbers--) = x;
++ }
++
++ XVECEXP(newpat, 0, 0) = XVECEXP(pattern, 0, 0);
++ return newpat;
+ }
+
+ void
+ insn_info::auto_inc_fixup (int regno, int size)
+ {
+ // debug_rtx (insn);
+-
+ rtx set0 = single_set (insn);
+ rtx set = set0;
+- SET_INSN_DELETED(insn);
+ if (is_compare ())
+ set = SET_SRC(set);
+
+@@ -876,7 +918,7 @@ insn_info::auto_inc_fixup (int regno, int size)
+ mem = XEXP(mem, 1);
+
+ rtx plus = XEXP(mem, 0);
+- if ((get_dst_mem_regno () == regno ? dst_mem_addr : src_mem_addr) == size)
++ if ((get_dst_mem_regno () == regno ? dst_mem_addr : src_mem_addr) == (unsigned) size)
+ {
+ XEXP(mem, 0) = XEXP(plus, 0);
+ (get_dst_mem_regno () == regno ? dst_mem_addr : src_mem_addr) = 0;
+@@ -886,8 +928,11 @@ insn_info::auto_inc_fixup (int regno, int size)
+ XEXP(plus, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(plus, 1)),
+ (get_dst_mem_regno () == regno ? dst_mem_addr : src_mem_addr) -= size);
+ }
+- insn = emit_insn_after (set0, insn);
+-// debug_rtx (insn);
++
++ rtx pattern = add_clobbers (insn);
++
++ SET_INSN_DELETED(insn);
++ insn = emit_insn_after (pattern, insn);
+ }
+
+ track_var *
+@@ -1383,15 +1428,14 @@ insn_info::set_insn (rtx_insn * newinsn)
+ fledder (single_set (insn));
+ }
+
+-void
+-insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol)
++rtx
++insn_info::make_absolute2base (unsigned regno, unsigned base, rtx with_symbol, bool apply)
+ {
+ rtx set = single_set (get_insn ());
+ rtx src = SET_SRC(set);
+ rtx dst = SET_DEST(set);
+- bool vola = src->volatil;
+- rtx pattern;
+ rtx reg = gen_raw_REG (SImode, regno);
++ bool vola = src->volatil;
+
+ if (is_dst_mem () && (has_dst_addr () || get_dst_symbol ()) && !has_dst_memreg () && get_dst_symbol () == with_symbol)
+ {
+@@ -1404,10 +1448,13 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol)
+ else
+ dst = gen_rtx_MEM (mode, gen_rtx_PLUS(SImode, reg, gen_rtx_CONST_INT (SImode, offset)));
+
+- dst_mem_reg = reg;
+- dst_mem = true;
+- dst_mem_addr = offset;
+- dst_plus = offset != 0;
++ if (apply)
++ {
++ dst_mem_reg = reg;
++ dst_mem = true;
++ dst_mem_addr = offset;
++ dst_plus = offset != 0;
++ }
+ }
+ }
+
+@@ -1438,16 +1485,27 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol)
+ }
+ }
+
+- src_mem_reg = reg;
+- src_mem = true;
+- src_mem_addr = offset;
+- src_plus = offset != 0;
++ if (apply)
++ {
++ src_mem_reg = reg;
++ src_mem = true;
++ src_mem_addr = offset;
++ src_plus = offset != 0;
++ }
+ }
+ }
+
+- pattern = gen_rtx_SET(dst, src);
++ rtx pattern = gen_rtx_SET(dst, src);
+ src->volatil = vola;
+
++ return pattern;
++}
++
++void
++insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol)
++{
++ rtx pattern = make_absolute2base (regno, base, with_symbol, true);
++
+ SET_INSN_DELETED(insn);
+ insn = emit_insn_after (pattern, insn);
+
+@@ -1506,7 +1564,7 @@ append_reg_usage (FILE * f, rtx_insn * insn)
+ if (be_very_verbose > 1)
+ fprintf (f, "\n\t\t\t\t\t|%d\t", ii.get_index ());
+ else
+- fprintf (f, "\n\t\t\t\t\t|\t", ii.get_index ());
++ fprintf (f, "\n\t\t\t\t\t|\t");
+ }
+
+ fprintf (f, "%c ", ii.in_proepi () == IN_PROLOGUE ? 'p' : ii.in_proepi () >= IN_EPILOGUE ? 'e' : ' ');
+@@ -1533,6 +1591,22 @@ append_reg_usage (FILE * f, rtx_insn * insn)
+
+ if (ii.is_use (FIRST_PSEUDO_REGISTER))
+ fprintf (f, ii.is_def (FIRST_PSEUDO_REGISTER) ? "+cc " : " cc ");
++ else
++ fprintf (f, " ");
++
++ // append fp usage info if present
++ if ((ii.get_use () | ii.get_def ()) & ~0xffff)
++ {
++ for (int j = 16; j < 24; ++j)
++ if (ii.is_use (j) || ii.is_def (j))
++ {
++ fprintf (f, ii.is_hard (j) ? "!" : " ");
++ fprintf (f, ii.is_def (j) ? ii.is_use (j) ? "*" : "+" : ii.is_myuse (j) ? "." : " ");
++ fprintf (f, "f%d ", j - 16);
++ }
++ else
++ fprintf (f, " ");
++ }
+
+ if (f == stderr)
+ fprintf (f, "\n");
+@@ -2024,7 +2098,6 @@ opt_reg_rename (void)
+ if (found.find (startat) != found.end () || !infos[startat].is_use (rename_regno))
+ continue;
+
+-
+ unsigned start = find_start (startat, rename_regno);
+ // printf ("label %d <- jump %d : start %d\n", pos, startat, start); fflush (stdout);
+ todo.insert (start);
+@@ -2042,7 +2115,7 @@ opt_reg_rename (void)
+
+ // printf ("label start check %d use %d\n", pos, bb.is_use (rename_regno) || bb.is_def(rename_regno)); fflush (stdout);
+
+- if (bb.is_use (rename_regno) || bb.is_def(rename_regno))
++ if (bb.is_use (rename_regno) || bb.is_def (rename_regno))
+ {
+ unsigned start = find_start (pos - 1, rename_regno);
+ todo.insert (start);
+@@ -2136,15 +2209,14 @@ opt_reg_rename (void)
+
+ for (std::set<unsigned>::iterator i = found.begin (); ok && i != found.end (); ++i)
+ {
+- rtx_insn * insn = infos[*i].get_insn ();
++ insn_info & rr = infos[*i];
++ rtx_insn * insn = rr.get_insn ();
+
+ /* temp rename. */
+ temp_reg_rename (locs, PATTERN (insn), oldregno, newregno);
+ if (!locs.empty ())
+ {
+- int num_clobbers_to_add = 0;
+- int insn_code_number = recog (PATTERN (insn), insn, &num_clobbers_to_add);
+- if (insn_code_number < 0 || !check_asm_operands (PATTERN (insn)))
++ if (insn_invalid_p (insn, 1))
+ ok = false;
+
+ /* undo temp change but keep loc and new register. */
+@@ -2160,6 +2232,12 @@ opt_reg_rename (void)
+ }
+
+ if (!ok)
++ {
++ cancel_changes (0);
++ continue;
++ }
++
++ if (!apply_change_group ())
+ continue;
+
+ log ("(r) opt_reg_rename %s -> %s (%d locs, start at %d)\n", reg_names[oldregno], reg_names[newregno],
+@@ -2527,18 +2605,15 @@ opt_strcpy ()
+ NOTICE_UPDATE_CC(PATTERN (reg2x), reg2x);
+ if (cc_status.flags == 0 && rtx_equal_p (dst, cc_status.value2))
+ {
+- int num_clobbers_to_add = 0;
+- int insn_code_number;
+-
+ rtx pattern = gen_rtx_SET(SET_DEST(single_set (reg2x)), SET_SRC(single_set (x2reg)));
+ rtx_insn * newinsn = make_insn_raw (pattern);
+- insn_code_number = recog (PATTERN (newinsn), newinsn, &num_clobbers_to_add);
+- if (insn_code_number >= 0 && check_asm_operands (PATTERN (newinsn)))
++
++ if (!insn_invalid_p (newinsn, 0))
+ {
+ log ("(s) opt_strcpy condition met, removing compare and joining insns - omit reg %s\n",
+ reg_names[REGNO(dst)]);
+
+- emit_insn_after (pattern, reg2x);
++ emit_insn_after (newinsn, reg2x);
+
+ SET_INSN_DELETED(x2reg);
+ SET_INSN_DELETED(reg2x);
+@@ -2646,21 +2721,21 @@ opt_commute_add_move (void)
+ rtx newmem = replace_equiv_address_nv (dst, pinc);
+
+ rtx_insn * newinsn = make_insn_raw (gen_rtx_SET(reg1dst, reg1src));
+- if (recog (PATTERN (newinsn), newinsn, 0) < 0 || !check_asm_operands (PATTERN (newinsn)))
+- continue;
+
+- if (validate_change (next, &SET_DEST(set2), newmem, 0))
++ if (!insn_invalid_p (newinsn, 1) && validate_change (next, &SET_DEST(set2), newmem, 1) && apply_change_group ())
+ {
+ log ("(a) commute_add_move found\n");
+
+ SET_INSN_DELETED(insn);
+
+- insn = emit_insn_before (PATTERN (newinsn), next);
++ insn = emit_insn_before (newinsn, next);
+
+ add_reg_note (next, REG_INC, reg1dst);
+
+ ++change_count;
+ }
++ else
++ cancel_changes (0);
+ }
+ return change_count;
+ }
+@@ -2722,8 +2797,8 @@ opt_const_cmp_to_sub (void)
+ lastsubval = pp.get_src_intval ();
+
+ // but still check for usage after this jump
+- j2l_iterator l = jump2label.find(index + 2);
+- if (l == jump2label.end())
++ j2l_iterator l = jump2label.find (index + 2);
++ if (l == jump2label.end ())
+ continue;
+
+ insn_info & label = infos[l->second + 1];
+@@ -2785,9 +2860,7 @@ opt_const_cmp_to_sub (void)
+
+ rtx_insn * subinsn = make_insn_raw (gen_rtx_SET(copyreg, sub));
+
+- int num_clobbers_to_add = 0;
+- int insn_code_number = recog (PATTERN (subinsn), subinsn, &num_clobbers_to_add);
+- if (insn_code_number < 0 || !check_asm_operands (PATTERN (subinsn)))
++ if (insn_invalid_p (subinsn, 0))
+ continue;
+
+ /* delete move #x,dy. */
+@@ -3726,7 +3799,7 @@ track_regs ()
+ * delete those insns.
+ */
+ static unsigned
+-opt_elim_dead_assign (unsigned blocked_regno)
++opt_elim_dead_assign (int blocked_regno)
+ {
+ track_regs ();
+
+@@ -3885,6 +3958,7 @@ opt_absolute (void)
+
+ if (freemask && found.size () > 2)
+ {
++ unsigned regno = bit2regno (freemask);
+ /* check again. */
+ for (std::vector<unsigned>::iterator k = found.begin (); k != found.end ();)
+ {
+@@ -3897,6 +3971,8 @@ opt_absolute (void)
+ k = found.erase (k);
+ else if (k_src && kk.get_src_mem_addr () - base > 0x7ffc)
+ k = found.erase (k);
++ else if (insn_invalid_p (make_insn_raw (kk.make_absolute2base (regno, base, with_symbol, false)), 0))
++ k = found.erase (k);
+ else
+ ++k;
+ }
+@@ -3916,6 +3992,7 @@ opt_absolute (void)
+ {
+ insn_info & kk = infos[*k];
+ kk.absolute2base (regno, base, with_symbol);
++ insn_invalid_p (kk.get_insn (), 0);
+ }
+
+ // load base into reg
+@@ -3958,174 +4035,194 @@ opt_absolute (void)
+ return change_count;
+ }
+
+-/*
+- * Convert a series of reg with offset ( (ax), 4(ax), 8(ax), ...) into autoincx ( (ax+), (ax+), (ax+), ...)
+- *
+- * 1. search a mem(reg) without offset and either src or dst is using that reg
+- * 2. follow paths until reg is dead
+- * 3. if there is another mem(reg) with offset check that
+- * a) offset fits last mode size
+- * b) all remaining insn using that reg can be updated by
+- * i) decrement the offset
+- * ii) decrement the add value
+- */
+-static unsigned
+-opt_autoinc ()
++static int
++try_auto_inc (unsigned index, insn_info & ii, rtx reg)
+ {
+- unsigned change_count = 0;
++ int regno = REGNO(reg);
++ unsigned size = GET_MODE_SIZE(ii.get_mode ());
++ if (size > 4)
++ return 0;
+
+- update_label2jump ();
++// log ("starting auto_inc search for %s at %d\n", reg_names[regno], index);
+
+- for (unsigned index = 0; index < infos.size (); ++index)
+- {
+- insn_info & ii = infos[index];
++ // track all fixups to modify
++ std::set<unsigned> fixups;
+
+- if (ii.in_proepi ())
+- continue;
++ // all paths to check
++ std::vector<unsigned> todo;
++ todo.push_back (index + 1);
+
+- rtx reg = 0;
+- if (ii.is_src_mem () && ii.get_src_mem_regno () >= 8 && !ii.get_src_mem_addr () && !ii.get_src_autoinc ()
+- && ii.get_src_mem_regno () != ii.get_dst_mem_regno ())
+- reg = ii.get_src_mem_reg ();
+- if (!reg && ii.is_dst_mem () && ii.get_dst_mem_regno () >= 8 && !ii.get_dst_intval () && !ii.get_dst_autoinc ()
+- && ii.get_src_mem_regno () != ii.get_dst_mem_regno ())
+- reg = ii.get_dst_mem_reg ();
+- if (!reg)
+- continue;
++ bool match_size = false;
++ bool ok = true;
++ std::set<unsigned> visited;
++ while (ok && todo.size () > 0)
++ {
++ unsigned pos = todo[todo.size () - 1];
++ todo.pop_back ();
+
+- int regno = REGNO(reg);
+- int size = GET_MODE_SIZE(ii.get_mode ());
+- if (size > 4)
+- continue;
++ if (pos == index)
++ {
++ ok = false;
++ break;
++ }
+
+-// log ("starting auto_inc search for %s at %d\n", reg_names[regno], index);
++ if (visited.find (pos) != visited.end ())
++ continue;
++ visited.insert (pos);
+
+- // track all fixups to modify
+- std::set<unsigned> fixups;
++ for (; pos < infos.size (); ++pos)
++ {
++ insn_info & jj = infos[pos];
+
+- // all paths to check
+- std::vector<unsigned> todo;
+- todo.push_back (index + 1);
++ // check all jumps labels for register usage
++ if (jj.is_label ())
++ {
++ for (l2j_iterator j = label2jump.find (jj.get_insn ()->u2.insn_uid), k = j;
++ j != label2jump.end () && j->first == k->first; ++j)
++ {
++ insn_info * ll = insn2info.find (j->second)->second;
++ if (ll->is_use (regno))
++ {
++ ok = false;
++ break;
++ }
++ }
++ if (ok)
++ continue;
++ break;
++ }
+
+- bool match_size = false;
+- bool ok = true;
+- std::set<unsigned> visited;
+- while (ok && todo.size () > 0)
+- {
+- unsigned pos = todo[todo.size () - 1];
+- todo.pop_back ();
++ // break if no longer used
++ if (!jj.is_use (regno))
++ break;
+
+- if (pos == index)
++ if (jj.in_proepi ())
+ {
+ ok = false;
+ break;
+ }
+
+- if (visited.find (pos) != visited.end ())
++ // add all labels
++ if (jj.is_jump ())
++ {
++ for (j2l_iterator j = jump2label.find (pos), k = j; j != jump2label.end () && j->first == k->first; ++j)
++ todo.push_back (j->second);
++ continue;
++ }
++
++ // not used directly
++ if (!jj.is_myuse (regno))
+ continue;
+- visited.insert (pos);
+
+- for (; pos < infos.size (); ++pos)
++ // can't fixup such kind of insn (yet)
++ if (single_set (jj.get_insn ()) == 0)
+ {
+- insn_info & jj = infos[pos];
++ ok = false;
++ break;
++ }
+
+- // check all jumps labels for register usage
+- if (jj.is_label ())
++ // if reg is src reg, op must be add and addend must be large enough
++ if (jj.get_src_regno () == regno || jj.get_src_mem_regno () == regno)
++ {
++ if (jj.get_src_intval () < (int) size || (jj.get_dst_mem_regno () == regno && jj.get_dst_addr () < size))
+ {
+- for (l2j_iterator j = label2jump.find (jj.get_insn ()->u2.insn_uid), k = j;
+- j != label2jump.end () && j->first == k->first; ++j)
+- {
+- insn_info * ll = insn2info.find (j->second)->second;
+- if (ll->is_use (regno))
+- {
+- ok = false;
+- break;
+- }
+- }
+- if (ok)
+- continue;
++ ok = false;
+ break;
+ }
+
+- // break if no longer used
+- if (!jj.is_use (regno))
+- break;
++ if (jj.get_dst_addr () == size)
++ match_size = true;
+
+- if (jj.in_proepi ())
++ fixups.insert (pos);
++ }
++ else if (jj.get_dst_mem_regno () == regno)
++ {
++ if (jj.get_dst_addr () < size)
+ {
+ ok = false;
+ break;
+ }
+
+- // add all labels
+- if (jj.is_jump ())
+- {
+- for (j2l_iterator j = jump2label.find (pos), k = j; j != jump2label.end () && j->first == k->first;
+- ++j)
+- todo.push_back (j->second);
+- continue;
+- }
++ if (jj.get_dst_addr () == size)
++ match_size = true;
+
+- // not used directly
+- if (!jj.is_myuse (regno))
+- continue;
++ fixups.insert (pos);
++ }
++ else
++ {
++ ok = false;
++ break;
++ }
+
+- // if reg is src reg, op must be add and addend must be large enough
+- if (jj.get_src_regno () == regno || jj.get_src_mem_regno () == regno)
+- {
+- if (jj.get_src_intval () < size || (jj.get_dst_mem_regno () == regno && jj.get_dst_addr () < size))
+- {
+- ok = false;
+- break;
+- }
++ // done if this is an add
++ if (ii.is_def (regno))
++ break;
++ }
++ }
+
+- if (jj.get_dst_addr () == size)
+- match_size = true;
++ if (!ok || !match_size || !fixups.size ())
++ return 0;;
+
+- fixups.insert (pos);
+- }
+- else if (jj.get_dst_mem_regno () == regno)
+- {
+- if (jj.get_dst_addr () < size)
+- {
+- ok = false;
+- break;
+- }
++ if (!ii.make_post_inc (regno))
++ return 0;
+
+- if (jj.get_dst_addr () == size)
+- match_size = true;
++ log ("(i) auto_inc for %s at %d\n", reg_names[regno], index);
+
+- fixups.insert (pos);
+- }
+- else
+- {
+- ok = false;
+- break;
+- }
++ // fix all offsets / adds
++ for (std::set<unsigned>::iterator k = fixups.begin (); k != fixups.end (); ++k)
++ {
++// log ("(i) fixup at %d\n", *k);
++ insn_info & kk = infos[*k];
++ kk.auto_inc_fixup (regno, size);
++ }
++ return 1;
++}
+
+- // done if this is an add
+- if (ii.is_def (regno))
+- break;
+- }
+- }
++/*
++ * Convert a series of reg with offset ( (ax), 4(ax), 8(ax), ...) into autoincx ( (ax+), (ax+), (ax+), ...)
++ *
++ * 1. search a mem(reg) without offset and either src or dst is using that reg
++ * 2. follow paths until reg is dead
++ * 3. if there is another mem(reg) with offset check that
++ * a) offset fits last mode size
++ * b) all remaining insn using that reg can be updated by
++ * i) decrement the offset
++ * ii) decrement the add value
++ */
++static unsigned
++opt_autoinc ()
++{
++ unsigned change_count = 0;
++
++ update_label2jump ();
++
++ for (unsigned index = 0; index < infos.size (); ++index)
++ {
++ insn_info & ii = infos[index];
++
++ if (ii.in_proepi ())
++ continue;
+
+- if (!ok || !match_size || !fixups.size ())
++ if (!INSN_P(ii.get_insn ()))
+ continue;
+
+- log ("(i) auto_inc for %s at %d\n", reg_names[regno], index);
++// // more than one reg used
++// if (ii.get_myuse () & (ii.get_myuse () - 1))
++// continue;
+
+- ii.make_post_inc (regno);
++// // don't if fp regs are touched
++// if ((ii.get_myuse () & 0xff0000))
++// continue;
+
+- // fix all offsets / adds
+- for (std::set<unsigned>::iterator k = fixups.begin (); k != fixups.end (); ++k)
+- {
+-// log ("(i) fixup at %d\n", *k);
+- insn_info & kk = infos[*k];
+- kk.auto_inc_fixup (regno, size);
+- }
++ rtx reg = 0;
++ if (ii.is_src_mem () && ii.get_src_mem_regno () >= 8 && !ii.get_src_mem_addr () && !ii.get_src_autoinc ()
++ && ii.get_src_mem_regno () != ii.get_dst_mem_regno ())
++ change_count += try_auto_inc (index, ii, ii.get_src_mem_reg ());
++
++ if (!reg && ii.is_dst_mem () && ii.get_dst_mem_regno () >= 8 && !ii.get_dst_intval () && !ii.get_dst_autoinc ()
++ && ii.get_src_mem_regno () != ii.get_dst_mem_regno ())
++ change_count += try_auto_inc (index, ii, ii.get_dst_mem_reg ());
+
+- ++change_count;
+- --index; // rerun insn to check src and dst
+ }
+
+ return change_count;
+@@ -4207,11 +4304,6 @@ namespace
+ bool do_absolute = strchr (string_bbb_opts, 'b') || strchr (string_bbb_opts, '+');
+ bool do_autoinc = strchr (string_bbb_opts, 'i') || strchr (string_bbb_opts, '+');
+
+-// ++xx;
+-// printf ("x: %d\n", xx);
+-// if (xx <= 48 || xx > 54)
+-// do_autoinc = false;
+-
+ if (be_very_verbose)
+ log ("ENTER\n");
+
+
+From 5c2dd1b12baffbf3e34da07e5fec09452f251d9e Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 12 Nov 2017 18:43:05 +0100
+Subject: [PATCH 227/303] autoinc improved, new register tracking is incorrect
+
+---
+ gcc/bbb-opts.c | 308 +++++++++++++++++++++++++++------------------------------
+ 1 file changed, 145 insertions(+), 163 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index c6aaa4dcb476..55cfae075f36 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -118,69 +118,72 @@ enum proepis
+
+ class track_var
+ {
++ unsigned * indexes;
+ rtx * values;
+ unsigned * versions;
+
+ public:
+ track_var (track_var const * o = 0) :
+- values ((rtx *) xcalloc (FIRST_PSEUDO_REGISTER, sizeof(rtx))), versions (
++ indexes ((unsigned *) xcalloc (FIRST_PSEUDO_REGISTER, sizeof(unsigned))), values (
++ (rtx *) xcalloc (FIRST_PSEUDO_REGISTER, sizeof(rtx))), versions (
+ (unsigned *) xcalloc (FIRST_PSEUDO_REGISTER, sizeof(unsigned)))
+ {
+ if (o)
+ assign (o);
+ }
+
+- rtx *
+- get_values () const
++ void
++ set (unsigned regno, unsigned index, rtx rtx, unsigned ver)
+ {
+- return values;
++ if (regno >= FIRST_PSEUDO_REGISTER)
++ return;
++
++ indexes[regno] = index;
++ values[regno] = rtx;
++ versions[regno] = ver;
+ }
+
+- void
+- set_version (unsigned regno, unsigned ver)
+- {
+- if (regno < FIRST_PSEUDO_REGISTER)
+- versions[regno] = ver;
++ unsigned get_index(unsigned regno) const {
++ return indexes[regno];
++ }
++
++ rtx get_value(unsigned regno) const {
++ return values[regno];
++ }
++
++ unsigned get_version(unsigned regno) const {
++ return versions[regno];
+ }
+
+ void
+ assign (track_var const * o) const
+ {
++ memcpy (indexes, o->indexes, FIRST_PSEUDO_REGISTER * sizeof(unsigned));
+ memcpy (values, o->values, FIRST_PSEUDO_REGISTER * sizeof(rtx));
+ memcpy (versions, o->versions, FIRST_PSEUDO_REGISTER * sizeof(unsigned));
+ }
+
+ /* only keep common values in both sides. */
+ void
+- merge (track_var * o)
++ merge (track_var * o, unsigned at)
+ {
+ for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+ {
+- if (values[i] && o->values[i] && rtx_equal_p (values[i], o->values[i]))
+- {
+- int code = GET_CODE(values[i]);
+- if (code != CONST_INT && code != CONST_FIXED && code != CONST_DOUBLE && versions[i] != o->versions[i])
+- values[i] = o->values[i] = 0;
+- }
+- else
++ indexes[i] = at;
++ if (versions[i] != o->versions[0] || !values[i] || !o->values[i] || !rtx_equal_p (values[i], o->values[i]))
+ values[i] = o->values[i] = 0;
+ }
+ }
+
+ /* true if a merge would not change anything. */
+ bool
+- contains (track_var const * o) const
++ no_merge_needed (track_var const * o) const
+ {
+ for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+ {
+- if (values[i] && o->values[i] && rtx_equal_p (values[i], o->values[i]))
+- {
+- int code = GET_CODE(values[i]);
+- if (code != CONST_INT && code != CONST_FIXED && code != CONST_DOUBLE && versions[i] != o->versions[i])
+- return false;
+- }
+- else if (values[i])
+- return false;
++ if (versions[i] != o->versions[0] || !values[i] || !o->values[i] || !rtx_equal_p (values[i], o->values[i]))
++ if (values[i])
++ return false;
+ }
+ return true;
+ }
+@@ -365,7 +368,7 @@ class insn_info
+ }
+
+ inline unsigned
+- get_dst_addr () const
++ get_dst_mem_addr () const
+ {
+ return dst_mem_addr;
+ }
+@@ -826,8 +829,8 @@ class insn_info
+ bool
+ insn_info::make_post_inc (int regno)
+ {
+- rtx pattern = PATTERN(insn);
+- rtx_insn * new_insn = make_insn_raw(pattern);
++ rtx pattern = PATTERN (insn);
++ rtx_insn * new_insn = make_insn_raw (pattern);
+
+ // convert into POST_INC
+ rtx set0 = single_set (new_insn);
+@@ -852,8 +855,8 @@ insn_info::make_post_inc (int regno)
+
+ SET_INSN_DELETED(insn);
+ (get_dst_mem_regno () == regno ? dst_autoinc : src_autoinc) = GET_MODE_SIZE(mode);
+- insn = emit_insn_after (PATTERN(new_insn), insn);
+- insn_invalid_p(insn, 0);
++ insn = emit_insn_after (PATTERN (new_insn), insn);
++ insn_invalid_p (insn, 0);
+
+ return 1;
+ }
+@@ -1010,11 +1013,15 @@ insn_info::scan_rtx (rtx x)
+ unsigned u = use;
+ unsigned mu = myuse;
+ use = myuse = 0;
+- scan_rtx (SET_DEST(x));
+- if (REG_P(SET_DEST(x)))
++ rtx dst = SET_DEST(x);
++ scan_rtx (dst);
++ if (REG_P(dst) || ((GET_CODE(dst) == STRICT_LOW_PART || GET_CODE(dst) == SUBREG) && REG_P(XEXP(dst, 0))))
+ {
+ def |= use;
+- use = u;
++ if ((GET_CODE(dst) == STRICT_LOW_PART || GET_CODE(dst) == SUBREG))
++ use |= u;
++ else
++ use = u;
+ myuse = mu;
+ }
+ scan_rtx (SET_SRC(x));
+@@ -1439,7 +1446,7 @@ insn_info::make_absolute2base (unsigned regno, unsigned base, rtx with_symbol, b
+
+ if (is_dst_mem () && (has_dst_addr () || get_dst_symbol ()) && !has_dst_memreg () && get_dst_symbol () == with_symbol)
+ {
+- unsigned addr = get_dst_addr ();
++ unsigned addr = get_dst_mem_addr ();
+ unsigned offset = addr - base;
+ if (offset <= 0x7ffe)
+ {
+@@ -3591,7 +3598,55 @@ opt_shrink_stack_frame (void)
+ return changed;
+ }
+
+-/* Update the insn_infos to 'know' the value for each register. */
++/* Update the insn_infos to 'know' the value for each register.
++ *
++ * atm only assignments to registers are optimized.
++ *
++ * We track register aliases:
++ *
++ * ;10
++ * move.l 4(a0),d0
++ *
++ * ;15
++ * move.l d0,d1
++ *
++ *
++ * ;18
++ * move.l d1,d2
++ *
++ * - results into d0 is an alias for d1 (and vice versa).
++ * - to identify if a register is still changed, we also track the line where it was assigned.
++ * - in addition to register aliases memory reads are tracked too for normal memory access (e.g. no auto inc)
++ * but not if the memory read is marked as volatile
++ *
++ * E.g.
++ *
++ * d0[10]: 4(a0)[10]
++ * d1[15]: d0[10]
++ * d2[18]: d1[15]
++ *
++ * with that information we know that d2[18] also contains 4(a0)[10]
++ *
++ * info to track per register:
++ * line index where the value was assigned
++ * rtx which was assigned - or null if not a usable rtx
++ * reg line index - if rtx is a register
++ *
++ * for each assignment which is not to a register the rtx are scanned and set to null on match
++ *
++ * on jumps the current state is duplicated and merged at the given label
++ *
++ * on merge only identical info is kept, rest is discarded
++ *
++ * for each insn first the track info for all defined regs is discarded before the new one is set.
++ *
++ *
++ * after the track info is complete, each insn is evaluated agains the track info.
++ *
++ * now redundant loads are found and eliminated
++ * also unused assignments are found an eliminated
++ *
++ */
+ static unsigned
+ track_regs ()
+ {
+@@ -3615,47 +3670,21 @@ track_regs ()
+ track_var * const track = todo.begin ()->second;
+ todo.erase (todo.begin ());
+
+- rtx * values = track->get_values ();
+- // track register aliases: know which register is used in what slot
+- // if a register changes, invalidate each slot
+- std::multimap<unsigned, unsigned> reg2slot;
+- for (unsigned slot = 0; slot < FIRST_PSEUDO_REGISTER; ++slot)
+- if (values[slot])
+- {
+- insn_info vv;
+- vv.scan_rtx (values[slot]);
+- for (unsigned regno = 0, m = vv.get_myuse (); m; ++regno, m >>= 1)
+- if (m & 1)
+- reg2slot.insert (std::make_pair (regno, slot));
+- }
+-
+- unsigned version = startpos;
+
+ for (unsigned index = startpos; index < infos.size (); ++index)
+ {
+ insn_info & ii = infos[index];
+
+ // already visited?
+- if (index != startpos && ii.is_visited () && ii.get_track_var ()->contains (track))
++ if (index != startpos && ii.is_visited () && ii.get_track_var ()->no_merge_needed(track))
+ break;
+
+ // only keep common values at labels
+ if (ii.is_label ())
+ {
+- version = index;
+ if (ii.is_visited ())
+ {
+- ii.get_track_var ()->merge (track);
+- reg2slot.clear ();
+- for (unsigned slot = 0; slot < FIRST_PSEUDO_REGISTER; ++slot)
+- if (values[slot])
+- {
+- insn_info vv;
+- vv.scan_rtx (values[slot]);
+- for (unsigned regno = 0, m = vv.get_myuse (); m; ++regno, m >>= 1)
+- if (m & 1)
+- reg2slot.insert (std::make_pair (regno, slot));
+- }
++ ii.get_track_var ()->merge (track, index);
+ }
+ else
+ {
+@@ -3675,18 +3704,11 @@ track_regs ()
+ unsigned def = ii.get_def ();
+ if (def)
+ {
+- for (int regno = 0; regno < 16; ++regno)
+- if ((1 << regno) & def)
+- {
+- values[regno] = 0;
+- // invalidate all referring registers
+- for (std::multimap<unsigned, unsigned>::iterator j = reg2slot.find (regno), k = j;
+- j != reg2slot.end () && j->first == k->first;)
+- {
+- values[j->second] = 0;
+- j = reg2slot.erase (j);
+- }
+- }
++ for (int regno = 0; regno < 24; ++regno)
++ {
++ if ((1 << regno) & def)
++ track->set(regno, index, 0, index);
++ }
+ }
+
+ if (ii.is_call ())
+@@ -3704,90 +3726,53 @@ track_regs ()
+ todo.insert (std::make_pair (i->second, new track_var (track)));
+
+ if (set && GET_CODE(SET_SRC(set)) == IF_THEN_ELSE)
+- {
+- version = index;
+ continue;
+- }
+
+ // unconditional jump
+ break;
+ }
+
+- if (!set)
++ if (!set || !ii.get_def ())
+ continue;
+
+- rtx src, dest;
+- if (ii.get_src_autoinc ())
+- {
+- int regno = ii.get_src_mem_regno ();
+- values[regno] = 0;
+- for (std::multimap<unsigned, unsigned>::iterator j = reg2slot.find (regno), k = j;
+- j != reg2slot.end () && j->first == k->first;)
+- {
+- values[j->second] = 0;
+- j = reg2slot.erase (j);
+- }
+- }
+-
+- if (ii.get_src_op () || ii.get_src_autoinc () || ((ii.get_myuse () - 1) & ii.get_myuse ()))
+- src = 0;
+- else
+- {
+- src = SET_SRC(set);
+- if (ii.is_src_mem () && src->volatil)
+- src = 0;
+- }
+-
+- if (ii.get_dst_autoinc ())
++ // invalidate all which are using the value from dest since that value changed
++ rtx dst = SET_DEST(set);
++ if (MEM_P(dst))
+ {
+- int regno = ii.get_dst_mem_regno ();
+- values[regno] = 0;
+- for (std::multimap<unsigned, unsigned>::iterator j = reg2slot.find (regno), k = j;
+- j != reg2slot.end () && j->first == k->first;)
++ for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+ {
+- values[j->second] = 0;
+- j = reg2slot.erase (j);
++ if (rtx_equal_p(dst, track->get_value(i)))
++ track->set(i, index, 0, index);
+ }
+ }
+
+- if (src == 0 || ii.get_src_op () || ii.get_dst_autoinc ())
+- dest = 0;
+- else
+- dest = SET_DEST(set);
+-
+- // track register values for now
+ int dregno = ii.get_dst_regno ();
+- int sregno = ii.get_src_regno ();
++ if (dregno < 0)
++ continue;
+
+- // track reg2slot
+- if (dregno >= 0)
+- {
+- for (unsigned regno = 0, m = ii.get_myuse (); m; ++regno, m >>= 1)
+- if (m & 1)
+- reg2slot.insert (std::make_pair (regno, dregno));
++ // operation, autoinf or more than one register used: can't cache
++ if (ii.get_src_op () || ii.get_src_autoinc () || ((ii.get_myuse () - 1) & ii.get_myuse ()))
++ continue;
+
+- if (sregno >= 0)
+- {
+- reg2slot.insert (std::make_pair (dregno, sregno));
+- reg2slot.insert (std::make_pair (sregno, dregno));
+- }
+- }
++ rtx src = SET_SRC(set);
++ if (ii.is_src_mem () && src->volatil)
++ continue;
+
+- if (sregno >= 0)
++ // add the entry - determine the version - use 0 for const values
++ unsigned version;
++ if (GET_CODE(src) != CONST_INT && GET_CODE(src) != CONST_FIXED && GET_CODE(src) != CONST_DOUBLE)
+ {
+- values[sregno] = dest;
+- track->set_version (sregno, version);
+- for (unsigned i = sregno + 1; i < END_REGNO (ii.get_src_reg ()); ++i)
+- values[i] = 0;
++ if (ii.get_src_regno() >= 0)
++ version = track->get_index(ii.get_src_regno());
++ else if (ii.get_src_mem_regno() >= 0)
++ version = track->get_index(ii.get_src_mem_regno());
++ else
++ version = index;
+ }
++ else
++ version = 0;
+
+- if (dregno >= 0)
+- {
+- values[dregno] = src;
+- track->set_version (dregno, version);
+- for (unsigned i = dregno + 1; i < END_REGNO (ii.get_dst_reg ()); ++i)
+- values[i] = 0;
+- }
++ track->set(dregno, index, src, version);
+ }
+ delete track;
+ }
+@@ -3822,26 +3807,23 @@ opt_elim_dead_assign (int blocked_regno)
+ ++change_count;
+ continue;
+ }
++
++ // check for redundant load
+ if (ii.get_src_op () == 0 && ii.get_dst_reg () && ii.get_dst_regno () != blocked_regno
+ && !ii.is_use (ii.get_dst_regno ()))
+ {
+- rtx cached_value = ii.get_track_var ()->get_values ()[ii.get_dst_regno ()];
+- rtx cached_value2 = 0;
+- if (cached_value && REG_P(cached_value) && REGNO(cached_value) < FIRST_PSEUDO_REGISTER)
+- {
+- cached_value2 = ii.get_track_var ()->get_values ()[REGNO(cached_value)];
+- if (!cached_value2) // no value for the reg -> reg is invalid too
+- cached_value = 0;
+- }
+- if (cached_value
+- && (rtx_equal_p (cached_value, SET_SRC(set))
+- || (cached_value2 && rtx_equal_p (cached_value2, SET_SRC(set)))))
++ track_var * track = ii.get_track_var();
++ rtx src = SET_SRC(set);
++ if (rtx_equal_p(track->get_value(ii.get_dst_regno()), src))
+ {
+-// fprintf(stderr, "cached_value: "); debug_rtx(cached_value);
+- log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]);
+- SET_INSN_DELETED(insn);
+- ++change_count;
+- continue;
++ if ((REG_P(src) && track->get_version(ii.get_dst_regno()) == track->get_index(REGNO(src)))
++ || !REG_P(src))
++ {
++ log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]);
++ SET_INSN_DELETED(insn);
++ ++change_count;
++ continue;
++ }
+ }
+ }
+ }
+@@ -3883,7 +3865,7 @@ opt_absolute (void)
+
+ std::vector<unsigned> found;
+ found.push_back (i);
+- int base = ii.get_dst_addr ();
++ int base = ii.get_dst_mem_addr ();
+ int max = base;
+ unsigned j = i + 1;
+ for (; j < infos.size (); ++j)
+@@ -3916,7 +3898,7 @@ opt_absolute (void)
+
+ if (j_dst)
+ {
+- int addr = jj.get_dst_addr ();
++ int addr = jj.get_dst_mem_addr ();
+ if (addr < base)
+ {
+ if (max - addr <= 0x7ffe)
+@@ -3967,7 +3949,7 @@ opt_absolute (void)
+ && kk.get_dst_symbol () == with_symbol;
+ bool k_src = kk.is_src_mem () && (kk.has_src_addr () || kk.get_src_symbol ()) && !kk.has_src_memreg ()
+ && kk.get_src_symbol () == with_symbol;
+- if (k_dst && kk.get_dst_addr () - base > 0x7ffc)
++ if (k_dst && kk.get_dst_mem_addr () - base > 0x7ffc)
+ k = found.erase (k);
+ else if (k_src && kk.get_src_mem_addr () - base > 0x7ffc)
+ k = found.erase (k);
+@@ -4124,26 +4106,26 @@ try_auto_inc (unsigned index, insn_info & ii, rtx reg)
+ // if reg is src reg, op must be add and addend must be large enough
+ if (jj.get_src_regno () == regno || jj.get_src_mem_regno () == regno)
+ {
+- if (jj.get_src_intval () < (int) size || (jj.get_dst_mem_regno () == regno && jj.get_dst_addr () < size))
++ if (jj.get_src_mem_addr () < size || (jj.get_dst_mem_regno () == regno && jj.get_dst_mem_addr () < size))
+ {
+ ok = false;
+ break;
+ }
+
+- if (jj.get_dst_addr () == size)
++ if (jj.get_src_mem_addr () == size)
+ match_size = true;
+
+ fixups.insert (pos);
+ }
+ else if (jj.get_dst_mem_regno () == regno)
+ {
+- if (jj.get_dst_addr () < size)
++ if (jj.get_dst_mem_addr () < size)
+ {
+ ok = false;
+ break;
+ }
+
+- if (jj.get_dst_addr () == size)
++ if (jj.get_dst_mem_addr () == size)
+ match_size = true;
+
+ fixups.insert (pos);
+
+From aa0ae94cf14aa246fb5f1907a086615e39278b3a Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 13 Nov 2017 22:20:19 +0100
+Subject: [PATCH 228/303] improved opt_autoinc() plus some bug fixes
+
+---
+ gcc/bbb-opts.c | 38 +++++++++++++++++++++-----------------
+ 1 file changed, 21 insertions(+), 17 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index c6aaa4dcb476..20126991e5d2 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -365,7 +365,7 @@ class insn_info
+ }
+
+ inline unsigned
+- get_dst_addr () const
++ get_dst_mem_addr () const
+ {
+ return dst_mem_addr;
+ }
+@@ -1010,10 +1010,14 @@ insn_info::scan_rtx (rtx x)
+ unsigned u = use;
+ unsigned mu = myuse;
+ use = myuse = 0;
+- scan_rtx (SET_DEST(x));
+- if (REG_P(SET_DEST(x)))
++ rtx dst = SET_DEST(x);
++ scan_rtx (dst);
++ if (REG_P(dst) || ((GET_CODE(dst) == STRICT_LOW_PART || GET_CODE(dst) == SUBREG) && REG_P(XEXP(dst, 0))))
+ {
+ def |= use;
++ if ((GET_CODE(dst) == STRICT_LOW_PART || GET_CODE(dst) == SUBREG))
++ use |= u;
++ else
+ use = u;
+ myuse = mu;
+ }
+@@ -1439,7 +1443,7 @@ insn_info::make_absolute2base (unsigned regno, unsigned base, rtx with_symbol, b
+
+ if (is_dst_mem () && (has_dst_addr () || get_dst_symbol ()) && !has_dst_memreg () && get_dst_symbol () == with_symbol)
+ {
+- unsigned addr = get_dst_addr ();
++ unsigned addr = get_dst_mem_addr ();
+ unsigned offset = addr - base;
+ if (offset <= 0x7ffe)
+ {
+@@ -3883,7 +3887,7 @@ opt_absolute (void)
+
+ std::vector<unsigned> found;
+ found.push_back (i);
+- int base = ii.get_dst_addr ();
++ int base = ii.get_dst_mem_addr ();
+ int max = base;
+ unsigned j = i + 1;
+ for (; j < infos.size (); ++j)
+@@ -3916,7 +3920,7 @@ opt_absolute (void)
+
+ if (j_dst)
+ {
+- int addr = jj.get_dst_addr ();
++ int addr = jj.get_dst_mem_addr ();
+ if (addr < base)
+ {
+ if (max - addr <= 0x7ffe)
+@@ -3967,7 +3971,7 @@ opt_absolute (void)
+ && kk.get_dst_symbol () == with_symbol;
+ bool k_src = kk.is_src_mem () && (kk.has_src_addr () || kk.get_src_symbol ()) && !kk.has_src_memreg ()
+ && kk.get_src_symbol () == with_symbol;
+- if (k_dst && kk.get_dst_addr () - base > 0x7ffc)
++ if (k_dst && kk.get_dst_mem_addr () - base > 0x7ffc)
+ k = found.erase (k);
+ else if (k_src && kk.get_src_mem_addr () - base > 0x7ffc)
+ k = found.erase (k);
+@@ -4124,26 +4128,26 @@ try_auto_inc (unsigned index, insn_info & ii, rtx reg)
+ // if reg is src reg, op must be add and addend must be large enough
+ if (jj.get_src_regno () == regno || jj.get_src_mem_regno () == regno)
+ {
+- if (jj.get_src_intval () < (int) size || (jj.get_dst_mem_regno () == regno && jj.get_dst_addr () < size))
++ if (jj.get_src_mem_addr () < size || (jj.get_dst_mem_regno () == regno && jj.get_dst_mem_addr () < size))
+ {
+ ok = false;
+ break;
+ }
+
+- if (jj.get_dst_addr () == size)
++ if (jj.get_src_mem_addr () == size)
+ match_size = true;
+
+ fixups.insert (pos);
+ }
+ else if (jj.get_dst_mem_regno () == regno)
+ {
+- if (jj.get_dst_addr () < size)
++ if (jj.get_dst_mem_addr () < size)
+ {
+ ok = false;
+ break;
+ }
+
+- if (jj.get_dst_addr () == size)
++ if (jj.get_dst_mem_addr () == size)
+ match_size = true;
+
+ fixups.insert (pos);
+@@ -4216,7 +4220,7 @@ opt_autoinc ()
+
+ rtx reg = 0;
+ if (ii.is_src_mem () && ii.get_src_mem_regno () >= 8 && !ii.get_src_mem_addr () && !ii.get_src_autoinc ()
+- && ii.get_src_mem_regno () != ii.get_dst_mem_regno ())
++ && ii.get_src_mem_regno () != ii.get_dst_mem_regno () && ii.get_src_mem_regno () != ii.get_dst_regno ())
+ change_count += try_auto_inc (index, ii, ii.get_src_mem_reg ());
+
+ if (!reg && ii.is_dst_mem () && ii.get_dst_mem_regno () >= 8 && !ii.get_dst_intval () && !ii.get_dst_autoinc ()
+@@ -4293,16 +4297,16 @@ namespace
+ if (be_very_verbose)
+ be_verbose = true;
+
+- bool do_opt_strcpy = strchr (string_bbb_opts, 's') || strchr (string_bbb_opts, '+');
+ bool do_commute_add_move = strchr (string_bbb_opts, 'a') || strchr (string_bbb_opts, '+');
+- bool do_propagate_moves = strchr (string_bbb_opts, 'p') || strchr (string_bbb_opts, '+');
++ bool do_absolute = strchr (string_bbb_opts, 'b') || strchr (string_bbb_opts, '+');
+ bool do_const_cmp_to_sub = strchr (string_bbb_opts, 'c') || strchr (string_bbb_opts, '+');
+- bool do_merge_add = strchr (string_bbb_opts, 'm') || strchr (string_bbb_opts, '+');
+ bool do_elim_dead_assign = strchr (string_bbb_opts, 'e') || strchr (string_bbb_opts, '+');
+- bool do_bb_reg_rename = strchr (string_bbb_opts, 'r') || strchr (string_bbb_opts, '+');
+ bool do_shrink_stack_frame = strchr (string_bbb_opts, 'f') || strchr (string_bbb_opts, '+');
+- bool do_absolute = strchr (string_bbb_opts, 'b') || strchr (string_bbb_opts, '+');
+ bool do_autoinc = strchr (string_bbb_opts, 'i') || strchr (string_bbb_opts, '+');
++ bool do_merge_add = strchr (string_bbb_opts, 'm') || strchr (string_bbb_opts, '+');
++ bool do_propagate_moves = strchr (string_bbb_opts, 'p') || strchr (string_bbb_opts, '+');
++ bool do_bb_reg_rename = strchr (string_bbb_opts, 'r') || strchr (string_bbb_opts, '+');
++ bool do_opt_strcpy = strchr (string_bbb_opts, 's') || strchr (string_bbb_opts, '+');
+
+ if (be_very_verbose)
+ log ("ENTER\n");
+
+From 7a4225792c22aaab94d962e6890fb0deaddfd015 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 14 Nov 2017 10:36:18 +0100
+Subject: [PATCH 229/303] fix possible stack corruption if sp is used in
+ assignments
+
+---
+ gcc/bbb-opts.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 20126991e5d2..d9b89c6e29ac 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -2993,12 +2993,17 @@ opt_merge_add (void)
+ static unsigned
+ track_sp ()
+ {
+-// reset visited flags
++// reset visited flags - also check if sp is used as REG src.
+ for (unsigned index = 0; index < infos.size (); ++index)
+ {
+ insn_info & ii = infos[index];
+ ii.clear_visited ();
+ ii.set_sp_offset (0);
++
++ // if sp is used as source, we cannot shrink the stack yet
++ // too complicated
++ if (ii.get_src_regno() == STACK_POINTER_REGNUM)
++ return -1;
+ }
+
+ // add entry point
+
+From 0ef223ac20734c9b1998f62b6bef5f04d9cbf789 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 14 Nov 2017 10:37:11 +0100
+Subject: [PATCH 230/303] update target-help to be complete and better readable
+
+---
+ gcc/config/m68k/amigaos.opt | 17 ++++++++++++++++-
+ 1 file changed, 16 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt
+index 9c08ba43196e..770cff6a4bd5 100644
+--- gcc/config/m68k/amigaos.opt
++++ gcc/config/m68k/amigaos.opt
+@@ -45,4 +45,19 @@ Specify startup binary
+
+ fbbb=
+ Target RejectNegative Report Var(string_bbb_opts) Joined
+--fbbb=\t\tEnable Bebbo's optimizations. Default: -fbbb=+\n valid letters:\n\t\t+\t\tenable all\n\t\t-\t\tdisable all\n\t\ta\t\tadd move optimization\n\t\tc\t\tcompare to sub\n\t\te\t\teliminate dead assignments\n\t\tf\t\tshrink stack frame\n\t\tm\t\tmerge add statements\n\t\tp\t\tpropagate move pairs from loops\n\t\tr\t\tadditional reg rename pass\n\t\tv\t\tbe verbose\n\t\tx or X\t\tdump insns
++-fbbb=Enable Bebbo's optimizations. \
+++ enable all optimizations \
++a commute add move instructions \
++b use register for base addresses \
++c convert load const and compare into a sub \
++e eliminate dead assignments + redundant loads \
++f shrink stack frame \
++i use post increment on addresses \
++m merge add and move statements \
++p propagate move assignment pairs out of loops \
++r register renaming to maybe save registers \
++s a strcpy optimization \
++v be verbose \
++V be very verbose \
++x dump insns \
++Default: -fbbb=+
+
+From 09c4f1cf165378985667aa9a82c1fa0403e60dd2 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 14 Nov 2017 10:49:16 +0100
+Subject: [PATCH 231/303] merge from devel1
+
+---
+ gcc/bbb-opts.c | 19 ++++++++++++-------
+ 1 file changed, 12 insertions(+), 7 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 55cfae075f36..47902cea4658 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -2996,12 +2996,17 @@ opt_merge_add (void)
+ static unsigned
+ track_sp ()
+ {
+-// reset visited flags
++// reset visited flags - also check if sp is used as REG src.
+ for (unsigned index = 0; index < infos.size (); ++index)
+ {
+ insn_info & ii = infos[index];
+ ii.clear_visited ();
+ ii.set_sp_offset (0);
++
++ // if sp is used as source, we cannot shrink the stack yet
++ // too complicated
++ if (ii.get_src_regno() == STACK_POINTER_REGNUM)
++ return -1;
+ }
+
+ // add entry point
+@@ -4198,7 +4203,7 @@ opt_autoinc ()
+
+ rtx reg = 0;
+ if (ii.is_src_mem () && ii.get_src_mem_regno () >= 8 && !ii.get_src_mem_addr () && !ii.get_src_autoinc ()
+- && ii.get_src_mem_regno () != ii.get_dst_mem_regno ())
++ && ii.get_src_mem_regno () != ii.get_dst_mem_regno () && ii.get_src_mem_regno () != ii.get_dst_regno ())
+ change_count += try_auto_inc (index, ii, ii.get_src_mem_reg ());
+
+ if (!reg && ii.is_dst_mem () && ii.get_dst_mem_regno () >= 8 && !ii.get_dst_intval () && !ii.get_dst_autoinc ()
+@@ -4275,16 +4280,16 @@ namespace
+ if (be_very_verbose)
+ be_verbose = true;
+
+- bool do_opt_strcpy = strchr (string_bbb_opts, 's') || strchr (string_bbb_opts, '+');
+ bool do_commute_add_move = strchr (string_bbb_opts, 'a') || strchr (string_bbb_opts, '+');
+- bool do_propagate_moves = strchr (string_bbb_opts, 'p') || strchr (string_bbb_opts, '+');
++ bool do_absolute = strchr (string_bbb_opts, 'b') || strchr (string_bbb_opts, '+');
+ bool do_const_cmp_to_sub = strchr (string_bbb_opts, 'c') || strchr (string_bbb_opts, '+');
+- bool do_merge_add = strchr (string_bbb_opts, 'm') || strchr (string_bbb_opts, '+');
+ bool do_elim_dead_assign = strchr (string_bbb_opts, 'e') || strchr (string_bbb_opts, '+');
+- bool do_bb_reg_rename = strchr (string_bbb_opts, 'r') || strchr (string_bbb_opts, '+');
+ bool do_shrink_stack_frame = strchr (string_bbb_opts, 'f') || strchr (string_bbb_opts, '+');
+- bool do_absolute = strchr (string_bbb_opts, 'b') || strchr (string_bbb_opts, '+');
+ bool do_autoinc = strchr (string_bbb_opts, 'i') || strchr (string_bbb_opts, '+');
++ bool do_merge_add = strchr (string_bbb_opts, 'm') || strchr (string_bbb_opts, '+');
++ bool do_propagate_moves = strchr (string_bbb_opts, 'p') || strchr (string_bbb_opts, '+');
++ bool do_bb_reg_rename = strchr (string_bbb_opts, 'r') || strchr (string_bbb_opts, '+');
++ bool do_opt_strcpy = strchr (string_bbb_opts, 's') || strchr (string_bbb_opts, '+');
+
+ if (be_very_verbose)
+ log ("ENTER\n");
+
+From 3d8120f2ca2cedeba1b42ece6e7c75f216324614 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 14 Nov 2017 11:11:17 +0100
+Subject: [PATCH 232/303] beautify target-help
+
+---
+ gcc/config/m68k/amigaos.opt | 30 +++++++++++++++---------------
+ 1 file changed, 15 insertions(+), 15 deletions(-)
+
+diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt
+index 770cff6a4bd5..d87f884f06b3 100644
+--- gcc/config/m68k/amigaos.opt
++++ gcc/config/m68k/amigaos.opt
+@@ -45,19 +45,19 @@ Specify startup binary
+
+ fbbb=
+ Target RejectNegative Report Var(string_bbb_opts) Joined
+--fbbb=Enable Bebbo's optimizations. \
+-+ enable all optimizations \
+-a commute add move instructions \
+-b use register for base addresses \
+-c convert load const and compare into a sub \
+-e eliminate dead assignments + redundant loads \
+-f shrink stack frame \
+-i use post increment on addresses \
+-m merge add and move statements \
+-p propagate move assignment pairs out of loops \
+-r register renaming to maybe save registers \
+-s a strcpy optimization \
+-v be verbose \
+-V be very verbose \
+-x dump insns \
++-fbbb=Enable Bebbo's optimizations.
+++ enable all optimizations
++a commute add move instructions
++b use register for base addresses
++c convert load const and compare into a sub
++e eliminate dead assignments + redundant loads
++f shrink stack frame
++i use post increment on addresses
++m merge add and move statements
++p propagate move assignment pairs out of loops
++r register renaming to maybe save registers
++s a strcpy optimization
++v be verbose
++V be very verbose
++x dump insns
+ Default: -fbbb=+
+
+From 3227e2247242531bd11713c4d6d12cec096196bc Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 14 Nov 2017 17:21:21 +0100
+Subject: [PATCH 233/303] reworked register tracking seems to work
+
+---
+ gcc/bbb-opts.c | 21 +++++++--------------
+ 1 file changed, 7 insertions(+), 14 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 47902cea4658..f971c402cf84 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -3706,14 +3706,19 @@ track_regs ()
+ if (ii.is_compare ())
+ continue;
+
++ int dregno = ii.get_dst_regno ();
+ unsigned def = ii.get_def ();
+ if (def)
+ {
+- for (int regno = 0; regno < 24; ++regno)
++ for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
+ {
+- if ((1 << regno) & def)
++ // register changed or used somehow
++ if ( ((1 << regno) & def) || (infos[track->get_index(regno)].get_myuse() & def))
+ track->set(regno, index, 0, index);
+ }
++ // clear on self update
++ if (def & ii.get_myuse())
++ track->set(dregno, index, 0, index);
+ }
+
+ if (ii.is_call ())
+@@ -3740,18 +3745,6 @@ track_regs ()
+ if (!set || !ii.get_def ())
+ continue;
+
+- // invalidate all which are using the value from dest since that value changed
+- rtx dst = SET_DEST(set);
+- if (MEM_P(dst))
+- {
+- for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+- {
+- if (rtx_equal_p(dst, track->get_value(i)))
+- track->set(i, index, 0, index);
+- }
+- }
+-
+- int dregno = ii.get_dst_regno ();
+ if (dregno < 0)
+ continue;
+
+
+From a8cd5ab8084d61d5d7ca31a840a737d4cf689022 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 14 Nov 2017 17:43:56 +0100
+Subject: [PATCH 234/303] fix opt_strcpy()
+
+---
+ gcc/bbb-opts.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index f971c402cf84..ca6e2acadf4d 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -2620,12 +2620,13 @@ opt_strcpy ()
+ log ("(s) opt_strcpy condition met, removing compare and joining insns - omit reg %s\n",
+ reg_names[REGNO(dst)]);
+
+- emit_insn_after (newinsn, reg2x);
+-
+ SET_INSN_DELETED(x2reg);
+ SET_INSN_DELETED(reg2x);
+ SET_INSN_DELETED(insn);
+
++ insn = emit_insn_after (pattern, reg2x);
++ insn_invalid_p (insn, 0);
++
+ ++change_count;
+ }
+ }
+
+From 0521364bbbcab54adfecf35c42cfec87ddeceb69 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 14 Nov 2017 17:44:24 +0100
+Subject: [PATCH 235/303] merge from devel1
+
+---
+ gcc/config/m68k/amigaos.opt | 17 ++++++++++++++++-
+ 1 file changed, 16 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt
+index 9c08ba43196e..d87f884f06b3 100644
+--- gcc/config/m68k/amigaos.opt
++++ gcc/config/m68k/amigaos.opt
+@@ -45,4 +45,19 @@ Specify startup binary
+
+ fbbb=
+ Target RejectNegative Report Var(string_bbb_opts) Joined
+--fbbb=\t\tEnable Bebbo's optimizations. Default: -fbbb=+\n valid letters:\n\t\t+\t\tenable all\n\t\t-\t\tdisable all\n\t\ta\t\tadd move optimization\n\t\tc\t\tcompare to sub\n\t\te\t\teliminate dead assignments\n\t\tf\t\tshrink stack frame\n\t\tm\t\tmerge add statements\n\t\tp\t\tpropagate move pairs from loops\n\t\tr\t\tadditional reg rename pass\n\t\tv\t\tbe verbose\n\t\tx or X\t\tdump insns
++-fbbb=Enable Bebbo's optimizations.
+++ enable all optimizations
++a commute add move instructions
++b use register for base addresses
++c convert load const and compare into a sub
++e eliminate dead assignments + redundant loads
++f shrink stack frame
++i use post increment on addresses
++m merge add and move statements
++p propagate move assignment pairs out of loops
++r register renaming to maybe save registers
++s a strcpy optimization
++v be verbose
++V be very verbose
++x dump insns
++Default: -fbbb=+
+
+From 8e8fcc48b69e50a83cf222e5a0166953d6bd7cbd Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 14 Nov 2017 23:30:53 +0100
+Subject: [PATCH 236/303] fix def flag in pre-/post-inc, disable elimination
+ for DI
+
+---
+ gcc/DATESTAMP | 2 +-
+ gcc/bbb-opts.c | 12 ++++++------
+ 2 files changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index c4335f1aad48..034f28535909 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20171011-233828
++20171114-232732
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index ca6e2acadf4d..29a70640b83f 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -1056,8 +1056,8 @@ insn_info::scan_rtx (rtx x)
+ }
+ }
+
+- if (code == CLOBBER)
+- def |= use;
++ if (code == POST_INC || code == PRE_DEC || code == CLOBBER)
++ def |= myuse;
+ }
+
+ void
+@@ -3704,9 +3704,6 @@ track_regs ()
+ ii.mark_visited ();
+ ii.get_track_var ()->assign (track);
+
+- if (ii.is_compare ())
+- continue;
+-
+ int dregno = ii.get_dst_regno ();
+ unsigned def = ii.get_def ();
+ if (def)
+@@ -3722,6 +3719,9 @@ track_regs ()
+ track->set(dregno, index, 0, index);
+ }
+
++ if (ii.is_compare ())
++ continue;
++
+ if (ii.is_call ())
+ continue;
+
+@@ -3799,7 +3799,7 @@ opt_elim_dead_assign (int blocked_regno)
+ if (!set)
+ continue;
+
+- if (ii.get_dst_reg () && ii.get_dst_regno () != blocked_regno && is_reg_dead (ii.get_dst_regno (), index))
++ if (ii.get_dst_reg () && REG_NREGS(ii.get_dst_reg ()) == 1 && ii.get_dst_regno () != blocked_regno && is_reg_dead (ii.get_dst_regno (), index))
+ {
+ log ("(e) %d: eliminate dead assign to %s\n", index, reg_names[ii.get_dst_regno ()]);
+ SET_INSN_DELETED(insn);
+
+From 11411a654f5ca127ba1fa43615ec543052d72cc4 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 15 Nov 2017 21:26:02 +0100
+Subject: [PATCH 237/303] refs #3 - forbid pea for baserel expressions inside
+ plus
+
+---
+ gcc/config/m68k/amigaos.h | 10 ----------
+ gcc/config/m68k/m68k.md | 2 +-
+ gcc/config/m68k/m68kamigaos.h | 10 ++++++++++
+ 3 files changed, 11 insertions(+), 11 deletions(-)
+
+diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h
+index 688f04e37ebb..d8b64576ef47 100644
+--- gcc/config/m68k/amigaos.h
++++ gcc/config/m68k/amigaos.h
+@@ -456,16 +456,6 @@ while (0)
+ bool
+ amigaos_rtx_costs (rtx, machine_mode, int, int, int *, bool);
+
+-/* SBF: macro to test for const via pic_reg. */
+-#define CONST_PLUS_PIC_REG_CONST_UNSPEC_P(x) \
+- (GET_CODE(x) == CONST \
+- && GET_CODE(XEXP(x, 0)) == PLUS \
+- && REG_P(XEXP(XEXP(x, 0), 0)) \
+- && REGNO(XEXP(XEXP(x, 0), 0)) == PIC_REG \
+- && GET_CODE(XEXP(XEXP(x, 0), 1)) == CONST \
+- && GET_CODE(XEXP(XEXP(XEXP(x, 0), 1), 0)) == UNSPEC \
+- )
+-
+ #undef TARGET_STRUCT_VALUE_RTX
+ #define TARGET_STRUCT_VALUE_RTX amigaos_struct_value_rtx
+ rtx
+diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
+index c9ea341789f4..71a54cededeb 100644
+--- gcc/config/m68k/m68k.md
++++ gcc/config/m68k/m68k.md
+@@ -1566,7 +1566,7 @@
+ (define_insn "pushasi"
+ [(set (match_operand:SI 0 "push_operand" "=m")
+ (match_operand:SI 1 "address_operand" "p"))]
+- ""
++ "(flag_pic < 3) || GET_CODE(operands[1]) != PLUS || !CONST_PLUS_PIC_REG_CONST_UNSPEC_P(XEXP(operands[1], 0))"
+ "pea %a1"
+ [(set_attr "type" "pea")])
+
+diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h
+index 7dc0e57f5cdc..cd099997bf07 100644
+--- gcc/config/m68k/m68kamigaos.h
++++ gcc/config/m68k/m68kamigaos.h
+@@ -755,3 +755,13 @@ extern int amiga_is_const_pic_ref(const_rtx x);
+
+ extern int
+ amigaos_function_arg_reg(unsigned regno);
++
++/* SBF: macro to test for const via pic_reg. */
++#define CONST_PLUS_PIC_REG_CONST_UNSPEC_P(x) \
++ (GET_CODE(x) == CONST \
++ && GET_CODE(XEXP(x, 0)) == PLUS \
++ && REG_P(XEXP(XEXP(x, 0), 0)) \
++ && REGNO(XEXP(XEXP(x, 0), 0)) == PIC_REG \
++ && GET_CODE(XEXP(XEXP(x, 0), 1)) == CONST \
++ && GET_CODE(XEXP(XEXP(XEXP(x, 0), 1), 0)) == UNSPEC \
++ )
+
+From 6f8c5e9a1995a1fbb15272251bfb15019486c053 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 15 Nov 2017 21:26:30 +0100
+Subject: [PATCH 238/303] update version
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 034f28535909..b8b68f869e68 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20171114-232732
++20171115-212610
+
+From b840b61ba578ffe6e2d06b7ce8106ce6a5308f68 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 16 Nov 2017 18:47:33 +0100
+Subject: [PATCH 239/303] fix auto_inc fixups
+
+---
+ gcc/bbb-opts.c | 101 ++++++++++++++++++++++++++++-----------------------------
+ 1 file changed, 50 insertions(+), 51 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 29a70640b83f..9770b93819e3 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -913,23 +913,41 @@ insn_info::auto_inc_fixup (int regno, int size)
+ else
+ XEXP(src, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(src, 1)), src_intval -= size);
+ }
+- else
++ else if (get_src_mem_regno () == regno)
+ {
+- rtx mem = get_dst_mem_regno () == regno ? SET_DEST(set) : SET_SRC(set);
+- // goto mem if there is an op
+- if (get_src_mem_regno () == regno && src_op)
+- mem = XEXP(mem, 1);
++ // src mem used ?
++ rtx mem = SET_SRC(set);
++ if (src_op)
++ {
++ if (MEM_P(XEXP(mem, 0)))
++ mem = XEXP(mem, 0);
++ else
++ mem = XEXP(mem, 1);
++ }
++ rtx plus = XEXP(mem, 0);
++
++ if (src_mem_addr == (unsigned) size)
++ {
++ XEXP(mem, 0) = XEXP(plus, 0);
++ src_mem_addr = 0;
++ src_plus = false;
++ }
++ else
++ XEXP(plus, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(plus, 1)), src_mem_addr -= size);
++ }
+
++ if (get_dst_mem_regno () == regno)
++ {
++ rtx mem = SET_DEST(set);
+ rtx plus = XEXP(mem, 0);
+- if ((get_dst_mem_regno () == regno ? dst_mem_addr : src_mem_addr) == (unsigned) size)
++ if (dst_mem_addr == (unsigned) size)
+ {
+ XEXP(mem, 0) = XEXP(plus, 0);
+- (get_dst_mem_regno () == regno ? dst_mem_addr : src_mem_addr) = 0;
+- (get_dst_mem_regno () == regno ? dst_plus : src_plus) = false;
++ dst_mem_addr = 0;
++ dst_plus = false;
+ }
+ else
+- XEXP(plus, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(plus, 1)),
+- (get_dst_mem_regno () == regno ? dst_mem_addr : src_mem_addr) -= size);
++ XEXP(plus, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(plus, 1)), dst_mem_addr -= size);
+ }
+
+ rtx pattern = add_clobbers (insn);
+@@ -4019,7 +4037,7 @@ opt_absolute (void)
+ static int
+ try_auto_inc (unsigned index, insn_info & ii, rtx reg)
+ {
+- int regno = REGNO(reg);
++ int const regno = REGNO(reg);
+ unsigned size = GET_MODE_SIZE(ii.get_mode ());
+ if (size > 4)
+ return 0;
+@@ -4034,18 +4052,14 @@ try_auto_inc (unsigned index, insn_info & ii, rtx reg)
+ todo.push_back (index + 1);
+
+ bool match_size = false;
+- bool ok = true;
+ std::set<unsigned> visited;
+- while (ok && todo.size () > 0)
++ while (todo.size () > 0)
+ {
+ unsigned pos = todo[todo.size () - 1];
+ todo.pop_back ();
+
+ if (pos == index)
+- {
+- ok = false;
+- break;
+- }
++ return 0;
+
+ if (visited.find (pos) != visited.end ())
+ continue;
+@@ -4063,13 +4077,8 @@ try_auto_inc (unsigned index, insn_info & ii, rtx reg)
+ {
+ insn_info * ll = insn2info.find (j->second)->second;
+ if (ll->is_use (regno))
+- {
+- ok = false;
+- break;
+- }
++ return 0;
+ }
+- if (ok)
+- continue;
+ break;
+ }
+
+@@ -4078,10 +4087,7 @@ try_auto_inc (unsigned index, insn_info & ii, rtx reg)
+ break;
+
+ if (jj.in_proepi ())
+- {
+- ok = false;
+- break;
+- }
++ return 0;
+
+ // add all labels
+ if (jj.is_jump ())
+@@ -4097,52 +4103,45 @@ try_auto_inc (unsigned index, insn_info & ii, rtx reg)
+
+ // can't fixup such kind of insn (yet)
+ if (single_set (jj.get_insn ()) == 0)
+- {
+- ok = false;
+- break;
+- }
++ return 0;
++
+
+ // if reg is src reg, op must be add and addend must be large enough
+- if (jj.get_src_regno () == regno || jj.get_src_mem_regno () == regno)
++ bool fix = false;
++ if (jj.get_src_mem_regno () == regno)
+ {
+- if (jj.get_src_mem_addr () < size || (jj.get_dst_mem_regno () == regno && jj.get_dst_mem_addr () < size))
+- {
+- ok = false;
+- break;
+- }
++ if (jj.get_src_mem_addr () < size)
++ return 0;
+
+ if (jj.get_src_mem_addr () == size)
+ match_size = true;
+
+- fixups.insert (pos);
++ fix = true;
+ }
+- else if (jj.get_dst_mem_regno () == regno)
++ if (jj.get_dst_mem_regno () == regno)
+ {
+ if (jj.get_dst_mem_addr () < size)
+- {
+- ok = false;
+- break;
+- }
++ return 0;
+
+ if (jj.get_dst_mem_addr () == size)
+ match_size = true;
+
+- fixups.insert (pos);
+- }
+- else
+- {
+- ok = false;
+- break;
++ fix = true;
+ }
+
++ if (!fix)
++ return 0;
++
++ fixups.insert (pos);
++
+ // done if this is an add
+ if (ii.is_def (regno))
+ break;
+ }
+ }
+
+- if (!ok || !match_size || !fixups.size ())
+- return 0;;
++ if (!match_size || !fixups.size ())
++ return 0;
+
+ if (!ii.make_post_inc (regno))
+ return 0;
+
+From a22dcf21bd29bb611cffba71f44be8bd8e374369 Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Fri, 17 Nov 2017 10:32:33 +0100
+Subject: [PATCH 240/303] bump version DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index b8b68f869e68..c6989ab7bfaf 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20171115-212610
++20171117-102900
+
+From 74fc8f7c5229526dcbeae19fc50276c872652706 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 17 Nov 2017 23:16:16 +0100
+Subject: [PATCH 241/303] modified reg tracking
+
+---
+ gcc/bbb-opts.c | 41 ++++++++++++++++++++++++++++++++---------
+ 1 file changed, 32 insertions(+), 9 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 9770b93819e3..294959ecb283 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -144,14 +144,20 @@ class track_var
+ }
+
+ unsigned get_index(unsigned regno) const {
++ if (regno >= FIRST_PSEUDO_REGISTER)
++ return 0;
+ return indexes[regno];
+ }
+
+ rtx get_value(unsigned regno) const {
++ if (regno >= FIRST_PSEUDO_REGISTER)
++ return 0;
+ return values[regno];
+ }
+
+ unsigned get_version(unsigned regno) const {
++ if (regno >= FIRST_PSEUDO_REGISTER)
++ return 0;
+ return versions[regno];
+ }
+
+@@ -169,8 +175,7 @@ class track_var
+ {
+ for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+ {
+- indexes[i] = at;
+- if (versions[i] != o->versions[0] || !values[i] || !o->values[i] || !rtx_equal_p (values[i], o->values[i]))
++ if (versions[i] != o->versions[0] || !rtx_equal_p (values[i], o->values[i]))
+ values[i] = o->values[i] = 0;
+ }
+ }
+@@ -181,7 +186,7 @@ class track_var
+ {
+ for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+ {
+- if (versions[i] != o->versions[0] || !values[i] || !o->values[i] || !rtx_equal_p (values[i], o->values[i]))
++ if (versions[i] != o->versions[0] || !rtx_equal_p (values[i], o->values[i]))
+ if (values[i])
+ return false;
+ }
+@@ -3723,13 +3728,13 @@ track_regs ()
+ ii.get_track_var ()->assign (track);
+
+ int dregno = ii.get_dst_regno ();
+- unsigned def = ii.get_def ();
++ unsigned def = ii.get_def () & 0xffffff;
+ if (def)
+ {
+ for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
+ {
+ // register changed or used somehow
+- if ( ((1 << regno) & def) || (infos[track->get_index(regno)].get_myuse() & def))
++ if ( ((1 << regno) & def) || (track->get_index(regno) && (infos[track->get_index(regno)].get_myuse() & def)))
+ track->set(regno, index, 0, index);
+ }
+ // clear on self update
+@@ -3827,13 +3832,19 @@ opt_elim_dead_assign (int blocked_regno)
+
+ // check for redundant load
+ if (ii.get_src_op () == 0 && ii.get_dst_reg () && ii.get_dst_regno () != blocked_regno
+- && !ii.is_use (ii.get_dst_regno ()))
++ && !ii.is_myuse (ii.get_dst_regno ()))
+ {
+ track_var * track = ii.get_track_var();
++
++// if (ii.get_src_regno() == 8 && ii.get_dst_regno() == 7)
++// printf("%d: move %d,%d: v=%d (%d->%d), i=%d (%d->%d)\n", index, ii.get_src_regno(), ii.get_dst_regno(),
++// track->get_version(ii.get_src_regno()), infos[track->get_version(ii.get_src_regno())].get_src_regno(), infos[track->get_version(ii.get_src_regno())].get_dst_regno(),
++// track->get_index(ii.get_dst_regno()), infos[track->get_index(ii.get_dst_regno())].get_src_regno(), infos[track->get_index(ii.get_dst_regno())].get_dst_regno());
++
+ rtx src = SET_SRC(set);
+ if (rtx_equal_p(track->get_value(ii.get_dst_regno()), src))
+ {
+- if ((REG_P(src) && track->get_version(ii.get_dst_regno()) == track->get_index(REGNO(src)))
++ if ((REG_P(src) && track->get_version(ii.get_dst_regno()) == track->get_index(ii.get_src_regno()))
+ || !REG_P(src))
+ {
+ log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]);
+@@ -3842,6 +3853,18 @@ opt_elim_dead_assign (int blocked_regno)
+ continue;
+ }
+ }
++ // check reverse assignment
++ if (REG_P(src))
++ {
++ if (REG_P(src) && rtx_equal_p(track->get_value(ii.get_src_regno()), SET_DEST(set))
++ && track->get_version(ii.get_src_regno()) == track->get_index(ii.get_dst_regno()))
++ {
++ log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]);
++ SET_INSN_DELETED(insn);
++ ++change_count;
++ continue;
++ }
++ }
+ }
+ }
+ return change_count;
+@@ -4308,10 +4331,10 @@ namespace
+ if (do_merge_add && opt_merge_add ())
+ done = 0;
+
+- if (do_absolute && opt_absolute ())
++ if (do_elim_dead_assign && opt_elim_dead_assign (STACK_POINTER_REGNUM))
+ done = 0, update_insns ();
+
+- if (do_elim_dead_assign && opt_elim_dead_assign (STACK_POINTER_REGNUM))
++ if (do_absolute && opt_absolute ())
+ done = 0, update_insns ();
+
+ if (do_autoinc && opt_autoinc ())
+
+From 7f672ad9e54bd8fc4cc1d13cac737374412481aa Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Sat, 18 Nov 2017 16:16:38 +0100
+Subject: [PATCH 242/303] bump version DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index c6989ab7bfaf..53f5062dcd68 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20171117-102900
++20171118-161638
+
+From b4f98bfecd75e74c6f488a8c2dd25b825bcb9c13 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 19 Nov 2017 12:45:24 +0100
+Subject: [PATCH 243/303] improved function type checking for __regargs,
+ __stdargs and asm register parameters
+
+---
+ gcc/c/c-decl.c | 29 ++++++++++++++++++--
+ gcc/config/m68k/amigaos.c | 70 +++++++++++++++++++++++++++++++++--------------
+ gcc/config/m68k/amigaos.h | 9 +++---
+ 3 files changed, 82 insertions(+), 26 deletions(-)
+
+diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
+index b0df4e1d9a65..42ebfeb9fa90 100644
+--- gcc/c/c-decl.c
++++ gcc/c/c-decl.c
+@@ -4441,7 +4441,32 @@ c_decl_attributes (tree *node, tree attributes, int flags)
+ attributes = tree_cons (get_identifier ("omp declare target"),
+ NULL_TREE, attributes);
+ }
+- return decl_attributes (node, attributes, flags);
++
++ tree returned_attrs = decl_attributes (node, attributes, flags);
++
++#ifdef TARGET_AMIGA
++ /* add an attribute to the function decl's type if there are asm register parameters. */
++ if (TREE_CODE (*node) == FUNCTION_DECL)
++ {
++ char * synthetic = "";
++ for (tree params = TYPE_ARG_TYPES(TREE_TYPE(*node)); params; params = TREE_CHAIN(params))
++ {
++ tree asmattr = lookup_attribute("asm", TYPE_ATTRIBUTES(TREE_VALUE(params)));
++ if (asmattr)
++ synthetic = concat(synthetic, reg_names[TREE_FIXED_CST_PTR(TREE_VALUE(asmattr))->data.low], 0);
++ }
++ if (strlen(synthetic) > 0)
++ {
++ tree asmid = get_identifier("asmregs");
++ tree syntheticid = get_identifier(synthetic);
++ tree newattr = tree_cons(asmid, syntheticid, NULL_TREE);
++
++ TYPE_ATTRIBUTES(TREE_TYPE(*node)) = chainon(newattr, TYPE_ATTRIBUTES(TREE_TYPE(*node)));
++ }
++ }
++#endif
++
++ return returned_attrs;
+ }
+
+
+@@ -5114,7 +5139,7 @@ push_parm_decl (const struct c_parm *parm, tree *expr)
+ TYPE_ATTRIBUTES(atype) = chainon (attrs, TYPE_ATTRIBUTES(atype));
+ }
+ TREE_TYPE(decl) = atype;
+-// printf("%s using %s, cdecl=%p, type=%p\n", IDENTIFIER_POINTER(DECL_NAME (decl), asmspec, decl, atype);
++// printf("%s using %s, cdecl=%p, type=%p\n", IDENTIFIER_POINTER(DECL_NAME (decl)), asmspec, decl, atype);
+ }
+ }
+ #endif
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index 53e01499341d..991c2905668f 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -393,7 +393,7 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl)
+
+ if (fntype)
+ {
+- tree attrs = decl ? DECL_ATTRIBUTES(decl) : NULL;
++ tree attrs = TYPE_ATTRIBUTES(fntype);
+ if (attrs)
+ {
+ if (lookup_attribute ("stkparm", attrs))
+@@ -622,27 +622,57 @@ amigaos_comp_type_attributes (const_tree type1, const_tree type2)
+ ways of passing arguments. */
+ if (TREE_CODE(type1) == FUNCTION_TYPE || TREE_CODE(type1) == METHOD_TYPE)
+ {
+- tree arg1, arg2;
+- arg1 = TYPE_ARG_TYPES(type1);
+- arg2 = TYPE_ARG_TYPES(type2);
+- for (; arg1 && arg2; arg1 = TREE_CHAIN(arg1), arg2 = TREE_CHAIN(arg2))
++ tree attrs1 = TYPE_ATTRIBUTES(type1);
++
++ tree asm1 = lookup_attribute("asmregs", attrs1);
++ tree stack1 = lookup_attribute("stkparm", attrs1);
++ tree reg1 = lookup_attribute("regparm", attrs1);
++
++ tree attrs2 = TYPE_ATTRIBUTES(type2);
++
++ tree asm2 = lookup_attribute("asmregs", attrs2);
++ tree stack2 = lookup_attribute("stkparm", attrs2);
++ tree reg2 = lookup_attribute("regparm", attrs2);
++
++ if (reg1)
+ {
+- tree attr1 = TYPE_ATTRIBUTES(arg1);
+- tree attr2 = TYPE_ATTRIBUTES(arg2);
+- if (strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(attr1))))
+- attr1 = NULL_TREE;
+- if (strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(attr2))))
+- attr2 = NULL_TREE;
+- if (attr1 && attr2)
+- {
+- if (TREE_FIXED_CST_PTR(TREE_VALUE(attr1))->data.low != TREE_FIXED_CST_PTR(TREE_VALUE(attr2))->data.low)
+- return 0;
+- }
+- else if (attr1 || attr2)
+- return 0; /* asm attribute only on one side. */
++ if (stack2 || asm2)
++ return 0;
++
++ int no1 = TREE_INT_CST_LOW(TREE_VALUE(reg1));
++ int no2 = reg2 ? TREE_INT_CST_LOW(TREE_VALUE(reg2)) : amigaos_regparm;
++ return no1 == no2;
++ }
++
++ if (reg2)
++ {
++ if (stack1 || asm1)
++ return 0;
++
++ int no2 = TREE_INT_CST_LOW(TREE_VALUE(reg2));
++ return amigaos_regparm == no2;
++ }
++
++ if (stack1) {
++ if (stack2)
++ return 1;
++ return amigaos_regparm == 0;
++ }
++
++ if (stack2)
++ return amigaos_regparm == 0;
++
++ if (asm1)
++ {
++ if (!asm2)
++ return 0;
++
++ return 0 == strcmp(IDENTIFIER_POINTER(TREE_VALUE(asm1)), IDENTIFIER_POINTER(TREE_VALUE(asm2)));
+ }
+- if (arg1 || arg2)
+- return 0; /* different count of parameters. */
++
++ if (asm2)
++ return 0;
++
+ }
+ return 1;
+ }
+diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h
+index d8b64576ef47..11dd88854160 100644
+--- gcc/config/m68k/amigaos.h
++++ gcc/config/m68k/amigaos.h
+@@ -444,10 +444,11 @@ while (0)
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
+ affects_type_identity } */
+ #define SUBTARGET_ATTRIBUTES \
+- { "regparm", 1, 1, true, false, false, amigaos_handle_type_attribute,\
+- false }, \
+- { "stkparm", 0, 0, true, false, false, amigaos_handle_type_attribute,\
+- false },
++ { "asmregs", 0, 0, false, false, false, 0, true }, \
++ { "regparm", 1, 1, false, true, true, amigaos_handle_type_attribute,\
++ true }, \
++ { "stkparm", 0, 0, false, true, true, amigaos_handle_type_attribute,\
++ true },
+
+ #define GOT_SYMBOL_NAME ""
+
+
+From 16411f7189d41024a5dc0b3a171b519e9295ee94 Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Sun, 19 Nov 2017 12:56:25 +0100
+Subject: [PATCH 244/303] bump version DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 53f5062dcd68..833a789eb3c6 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20171118-161638
++20171119-125625
+
+From 5d5c1d671aef73f71094976d17cd54a709582274 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 20 Nov 2017 09:55:01 +0100
+Subject: [PATCH 245/303] refs #3 - block an invalid combined insn
+
+---
+ gcc/config/m68k/amigaos.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index 991c2905668f..b65059edf2fa 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -941,7 +941,7 @@ amigaos_legitimate_combined_insn (rtx_insn * insn)
+ return true;
+
+ x = XEXP(x, 0);
+- if (GET_CODE(x) != NOT)
++ if (GET_CODE(x) != NOT && GET_CODE(x) != NEG)
+ return true;
+
+ x = XEXP(x, 0);
+
+From ca2ff3994ec1def3da8e9df51c0e80614c304784 Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Mon, 20 Nov 2017 16:07:27 +0100
+Subject: [PATCH 246/303] bump version DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 833a789eb3c6..0e38b8ced4de 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20171119-125625
++20171120-160727
+
+From 06d2e5b1b649b8f64333cdab447c70df3eb22ee9 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 23 Nov 2017 19:31:46 +0100
+Subject: [PATCH 247/303] refs #3 - added workarounds for baserel modes
+
+added an additional pass to convert combined baserel insns into correct form
+fixed peephole optimizer to leave pea insns untouched
+---
+ gcc/bbb-opts.c | 179 +++++++++++++++++++++++++++++++++++------
+ gcc/config/m68k/constraints.md | 2 +-
+ gcc/config/m68k/m68k.md | 4 +-
+ gcc/passes.c | 10 +--
+ gcc/passes.def | 1 +
+ gcc/recog.c | 12 +++
+ gcc/tree-pass.h | 1 +
+ 7 files changed, 175 insertions(+), 34 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 294959ecb283..a4fee5f446b0 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -143,19 +143,25 @@ class track_var
+ versions[regno] = ver;
+ }
+
+- unsigned get_index(unsigned regno) const {
++ unsigned
++ get_index (unsigned regno) const
++ {
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ return 0;
+ return indexes[regno];
+ }
+
+- rtx get_value(unsigned regno) const {
++ rtx
++ get_value (unsigned regno) const
++ {
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ return 0;
+ return values[regno];
+ }
+
+- unsigned get_version(unsigned regno) const {
++ unsigned
++ get_version (unsigned regno) const
++ {
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ return 0;
+ return versions[regno];
+@@ -948,7 +954,7 @@ insn_info::auto_inc_fixup (int regno, int size)
+ if (dst_mem_addr == (unsigned) size)
+ {
+ XEXP(mem, 0) = XEXP(plus, 0);
+- dst_mem_addr = 0;
++ dst_mem_addr = 0;
+ dst_plus = false;
+ }
+ else
+@@ -3029,7 +3035,7 @@ track_sp ()
+
+ // if sp is used as source, we cannot shrink the stack yet
+ // too complicated
+- if (ii.get_src_regno() == STACK_POINTER_REGNUM)
++ if (ii.get_src_regno () == STACK_POINTER_REGNUM)
+ return -1;
+ }
+
+@@ -3699,13 +3705,12 @@ track_regs ()
+ track_var * const track = todo.begin ()->second;
+ todo.erase (todo.begin ());
+
+-
+ for (unsigned index = startpos; index < infos.size (); ++index)
+ {
+ insn_info & ii = infos[index];
+
+ // already visited?
+- if (index != startpos && ii.is_visited () && ii.get_track_var ()->no_merge_needed(track))
++ if (index != startpos && ii.is_visited () && ii.get_track_var ()->no_merge_needed (track))
+ break;
+
+ // only keep common values at labels
+@@ -3734,12 +3739,13 @@ track_regs ()
+ for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
+ {
+ // register changed or used somehow
+- if ( ((1 << regno) & def) || (track->get_index(regno) && (infos[track->get_index(regno)].get_myuse() & def)))
+- track->set(regno, index, 0, index);
++ if (((1 << regno) & def)
++ || (track->get_index (regno) && (infos[track->get_index (regno)].get_myuse () & def)))
++ track->set (regno, index, 0, index);
+ }
+ // clear on self update
+- if (def & ii.get_myuse())
+- track->set(dregno, index, 0, index);
++ if (def & ii.get_myuse ())
++ track->set (dregno, index, 0, index);
+ }
+
+ if (ii.is_compare ())
+@@ -3760,7 +3766,7 @@ track_regs ()
+ todo.insert (std::make_pair (i->second, new track_var (track)));
+
+ if (set && GET_CODE(SET_SRC(set)) == IF_THEN_ELSE)
+- continue;
++ continue;
+
+ // unconditional jump
+ break;
+@@ -3784,17 +3790,17 @@ track_regs ()
+ unsigned version;
+ if (GET_CODE(src) != CONST_INT && GET_CODE(src) != CONST_FIXED && GET_CODE(src) != CONST_DOUBLE)
+ {
+- if (ii.get_src_regno() >= 0)
+- version = track->get_index(ii.get_src_regno());
+- else if (ii.get_src_mem_regno() >= 0)
+- version = track->get_index(ii.get_src_mem_regno());
++ if (ii.get_src_regno () >= 0)
++ version = track->get_index (ii.get_src_regno ());
++ else if (ii.get_src_mem_regno () >= 0)
++ version = track->get_index (ii.get_src_mem_regno ());
+ else
+ version = index;
+ }
+ else
+ version = 0;
+
+- track->set(dregno, index, src, version);
++ track->set (dregno, index, src, version);
+ }
+ delete track;
+ }
+@@ -3822,7 +3828,8 @@ opt_elim_dead_assign (int blocked_regno)
+ if (!set)
+ continue;
+
+- if (ii.get_dst_reg () && REG_NREGS(ii.get_dst_reg ()) == 1 && ii.get_dst_regno () != blocked_regno && is_reg_dead (ii.get_dst_regno (), index))
++ if (ii.get_dst_reg () && REG_NREGS(ii.get_dst_reg ()) == 1 && ii.get_dst_regno () != blocked_regno
++ && is_reg_dead (ii.get_dst_regno (), index))
+ {
+ log ("(e) %d: eliminate dead assign to %s\n", index, reg_names[ii.get_dst_regno ()]);
+ SET_INSN_DELETED(insn);
+@@ -3834,7 +3841,7 @@ opt_elim_dead_assign (int blocked_regno)
+ if (ii.get_src_op () == 0 && ii.get_dst_reg () && ii.get_dst_regno () != blocked_regno
+ && !ii.is_myuse (ii.get_dst_regno ()))
+ {
+- track_var * track = ii.get_track_var();
++ track_var * track = ii.get_track_var ();
+
+ // if (ii.get_src_regno() == 8 && ii.get_dst_regno() == 7)
+ // printf("%d: move %d,%d: v=%d (%d->%d), i=%d (%d->%d)\n", index, ii.get_src_regno(), ii.get_dst_regno(),
+@@ -3842,9 +3849,9 @@ opt_elim_dead_assign (int blocked_regno)
+ // track->get_index(ii.get_dst_regno()), infos[track->get_index(ii.get_dst_regno())].get_src_regno(), infos[track->get_index(ii.get_dst_regno())].get_dst_regno());
+
+ rtx src = SET_SRC(set);
+- if (rtx_equal_p(track->get_value(ii.get_dst_regno()), src))
++ if (rtx_equal_p (track->get_value (ii.get_dst_regno ()), src))
+ {
+- if ((REG_P(src) && track->get_version(ii.get_dst_regno()) == track->get_index(ii.get_src_regno()))
++ if ((REG_P(src) && track->get_version (ii.get_dst_regno ()) == track->get_index (ii.get_src_regno ()))
+ || !REG_P(src))
+ {
+ log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]);
+@@ -3856,8 +3863,8 @@ opt_elim_dead_assign (int blocked_regno)
+ // check reverse assignment
+ if (REG_P(src))
+ {
+- if (REG_P(src) && rtx_equal_p(track->get_value(ii.get_src_regno()), SET_DEST(set))
+- && track->get_version(ii.get_src_regno()) == track->get_index(ii.get_dst_regno()))
++ if (REG_P(src) && rtx_equal_p (track->get_value (ii.get_src_regno ()), SET_DEST(set))
++ && track->get_version (ii.get_src_regno ()) == track->get_index (ii.get_dst_regno ()))
+ {
+ log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]);
+ SET_INSN_DELETED(insn);
+@@ -4128,7 +4135,6 @@ try_auto_inc (unsigned index, insn_info & ii, rtx reg)
+ if (single_set (jj.get_insn ()) == 0)
+ return 0;
+
+-
+ // if reg is src reg, op must be add and addend must be large enough
+ bool fix = false;
+ if (jj.get_src_mem_regno () == regno)
+@@ -4379,3 +4385,128 @@ make_pass_bbb_optimizations (gcc::context * ctxt)
+ {
+ return new pass_bbb_optimizations (ctxt);
+ }
++
++namespace
++{
++
++ const pass_data pass_data_bbb_baserel =
++ { RTL_PASS, /* type */
++ "bebbo's-baserel fixer", /* name */
++ OPTGROUP_NONE, /* optinfo_flags */
++ TV_NONE, /* tv_id */
++ 0, /* properties_required */
++ 0, /* properties_provided */
++ 0, /* properties_destroyed */
++ 0, /* todo_flags_start */
++ 0, //( TODO_df_finish | TODO_df_verify), /* todo_flags_finish */
++ };
++
++ class pass_bbb_baserel : public rtl_opt_pass
++ {
++ public:
++ pass_bbb_baserel (gcc::context *ctxt) :
++ rtl_opt_pass (pass_data_bbb_baserel, ctxt), pp (0)
++ {
++ }
++
++ /* opt_pass methods: */
++ virtual bool
++ gate (function *)
++ {
++ return TARGET_AMIGA && flag_pic >= 3;
++ }
++
++ virtual unsigned int
++ execute (function *)
++ {
++ return execute_bbb_baserel ();
++ }
++
++ opt_pass *
++ clone ()
++ {
++ pass_bbb_baserel * bbb = new pass_bbb_baserel (m_ctxt);
++ return bbb;
++ }
++
++ unsigned int pp;
++
++ unsigned
++ execute_bbb_baserel (void);
++ };
++// class pass_bbb_optimizations
++
++ /* Main entry point to the pass. */
++ unsigned
++ pass_bbb_baserel::execute_bbb_baserel (void)
++ {
++ rtx_insn *insn, *next;
++ for (insn = get_insns (); insn; insn = next)
++ {
++ next = NEXT_INSN (insn);
++
++ if (NONJUMP_INSN_P(insn))
++ {
++ rtx set = single_set (insn);
++ if (!set)
++ continue;
++
++ rtx * src = &SET_SRC(set);
++ if (MEM_P(*src))
++ src = &XEXP(*src, 0);
++
++ bool ispicref = false;
++ // fix add PLUS/MINUS into the unspec offset
++ if (GET_CODE(*src) == PLUS || GET_CODE(*src) == MINUS)
++ {
++ if (CONST_PLUS_PIC_REG_CONST_UNSPEC_P(XEXP(*src, 0)))
++ {
++ bool isplus = GET_CODE(*src) == PLUS;
++ rtx offset = XEXP(*src, 1);
++
++ // unlink PLUS/MINUS
++ *src = XEXP(*src, 0);
++
++ rtx plus = XEXP(*src, 0);
++ rtx cnst = XEXP(plus, 1);
++ rtx unspec = XEXP(cnst, 0);
++
++ XVECEXP(unspec, 0, 0) = gen_rtx_PLUS(SImode, XVECEXP(unspec, 0, 0), gen_rtx_CONST_INT (SImode, isplus ? INTVAL(offset) : -INTVAL(offset)));
++
++ ispicref = true;
++ }
++ }
++ else
++ ispicref = CONST_PLUS_PIC_REG_CONST_UNSPEC_P(*src);
++
++ if (ispicref)
++ {
++ rtx dest = SET_DEST(set);
++ if (MEM_P(dest) && GET_CODE(XEXP(dest, 0)) != PRE_DEC
++ )
++ {
++ // split the insn
++ rtx reg = gen_reg_rtx (Pmode);
++
++ rtx pat0 = gen_rtx_SET(reg, *src);
++ rtx_insn * n0 = emit_insn_before(pat0, insn);
++
++ rtx pat1 = gen_rtx_SET(dest, reg);
++ rtx_insn * n1 = emit_insn_before(pat1, insn);
++
++ SET_INSN_DELETED(insn);
++ }
++ }
++ }
++ }
++
++ return 0;
++ }
++
++} // anon namespace
++
++rtl_opt_pass *
++make_pass_bbb_baserel (gcc::context * ctxt)
++{
++ return new pass_bbb_baserel (ctxt);
++}
+diff --git a/gcc/config/m68k/constraints.md b/gcc/config/m68k/constraints.md
+index 94a785dc95b6..0d9b1b69ab18 100644
+--- gcc/config/m68k/constraints.md
++++ gcc/config/m68k/constraints.md
+@@ -101,7 +101,7 @@
+ "Used for operands that satisfy 's' without PIC stuff, when -mpcrel is not in effect."
+ (and (match_code "symbol_ref,label_ref,const")
+ (match_test "!TARGET_PCREL")
+- (match_test "!flag_pic || GET_CODE(op) != CONST || GET_CODE (XEXP (op, 0)) == SYMBOL_REF || GET_CODE (XEXP (op, 0)) == LABEL_REF")))
++ (match_test "!flag_pic || !CONST_PLUS_PIC_REG_CONST_UNSPEC_P(op)")))
+
+ (define_memory_constraint "Q"
+ "Means address register indirect addressing mode."
+diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
+index 71a54cededeb..906fde496031 100644
+--- gcc/config/m68k/m68k.md
++++ gcc/config/m68k/m68k.md
+@@ -1564,9 +1564,9 @@
+ ;; so we will prefer it to them.
+
+ (define_insn "pushasi"
+- [(set (match_operand:SI 0 "push_operand" "=m")
++ [(set (match_operand:SI 0 "push_operand" "=<")
+ (match_operand:SI 1 "address_operand" "p"))]
+- "(flag_pic < 3) || GET_CODE(operands[1]) != PLUS || !CONST_PLUS_PIC_REG_CONST_UNSPEC_P(XEXP(operands[1], 0))"
++ ""
+ "pea %a1"
+ [(set_attr "type" "pea")])
+
+diff --git a/gcc/passes.c b/gcc/passes.c
+index 321adbc61e2d..407160f4e4d6 100644
+--- gcc/passes.c
++++ gcc/passes.c
+@@ -2276,18 +2276,14 @@ void dump_insns(char const * name)
+ for (insn = get_insns(); insn; insn = next)
+ {
+ next = NEXT_INSN(insn);
+- debug_rtx(insn);
+-#if 0
++#if 1
+ if (NONJUMP_INSN_P (insn))
+ {
+- rtx x, y, set= single_set (insn);
++ rtx set= single_set (insn);
+ if (!set)
+ continue;
+- x = y = SET_SRC(set);
+
+- while (GET_CODE(y) == CONST || GET_CODE(y) == PLUS)
+- y = XEXP(y, 0);
+- if (x != y && REG_P(y) && REGNO(y) == PIC_REG)
++ if (CONST_PLUS_PIC_REG_CONST_UNSPEC_P(SET_SRC(set)) && MEM_P(SET_DEST(set)))
+ debug_rtx(insn);
+ }
+ #endif
+diff --git a/gcc/passes.def b/gcc/passes.def
+index 6af49b56fb03..61d0e4d47377 100644
+--- gcc/passes.def
++++ gcc/passes.def
+@@ -386,6 +386,7 @@ along with GCC; see the file COPYING3. If not see
+ NEXT_PASS (pass_gen_hsail);
+
+ NEXT_PASS (pass_expand);
++ NEXT_PASS (pass_bbb_baserel);
+
+ NEXT_PASS (pass_rest_of_compilation);
+ PUSH_INSERT_PASSES_WITHIN (pass_rest_of_compilation)
+diff --git a/gcc/recog.c b/gcc/recog.c
+index 92b2aa31a777..1b215f350fd6 100644
+--- gcc/recog.c
++++ gcc/recog.c
+@@ -3249,9 +3249,21 @@ peep2_attempt (basic_block bb, rtx_insn *insn, int match_len, rtx_insn *attempt)
+ rtx_insn *new_insn;
+ bool was_call = false;
+
++#ifdef TARGET_AMIGA
++ /* SBF: splitting may yield invalid insns -> avoid it for the special pea insn! */
++ for (int i = 0; i <= match_len; ++i)
++ {
++ rtx_insn * insn0 = peep2_insn_data[i].insn;
++ rtx set0 = single_set(insn0);
++ if (set0 && CONST_PLUS_PIC_REG_CONST_UNSPEC_P(SET_SRC(set0)) && MEM_P(SET_DEST(set0)))
++ return 0;
++ }
++#endif
++
+ /* If we are splitting an RTX_FRAME_RELATED_P insn, do not allow it to
+ match more than one insn, or to be split into more than one insn. */
+ old_insn = peep2_insn_data[peep2_current].insn;
++
+ if (RTX_FRAME_RELATED_P (old_insn))
+ {
+ bool any_note = false;
+diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
+index b3f66ad529b9..76c0996850f4 100644
+--- gcc/tree-pass.h
++++ gcc/tree-pass.h
+@@ -591,6 +591,7 @@ extern rtl_opt_pass *make_pass_branch_target_load_optimize2 (gcc::context
+ extern rtl_opt_pass *make_pass_leaf_regs (gcc::context *ctxt);
+ extern rtl_opt_pass *make_pass_split_before_sched2 (gcc::context *ctxt);
+ extern rtl_opt_pass *make_pass_bbb_optimizations (gcc::context *ctxt);
++extern rtl_opt_pass *make_pass_bbb_baserel (gcc::context *ctxt);
+ extern rtl_opt_pass *make_pass_compare_elim_after_reload (gcc::context *ctxt);
+ extern rtl_opt_pass *make_pass_sched2 (gcc::context *ctxt);
+ extern rtl_opt_pass *make_pass_stack_regs (gcc::context *ctxt);
+
+From 4032d56eb771309d6aac6cbee68ce0bd2412e3e4 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 23 Nov 2017 20:18:51 +0100
+Subject: [PATCH 248/303] refs #3 fix npe if pattern == 0
+
+---
+ gcc/recog.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/gcc/recog.c b/gcc/recog.c
+index 1b215f350fd6..de2340518e52 100644
+--- gcc/recog.c
++++ gcc/recog.c
+@@ -3254,6 +3254,8 @@ peep2_attempt (basic_block bb, rtx_insn *insn, int match_len, rtx_insn *attempt)
+ for (int i = 0; i <= match_len; ++i)
+ {
+ rtx_insn * insn0 = peep2_insn_data[i].insn;
++ if (!PATTERN(insn0))
++ continue;
+ rtx set0 = single_set(insn0);
+ if (set0 && CONST_PLUS_PIC_REG_CONST_UNSPEC_P(SET_SRC(set0)) && MEM_P(SET_DEST(set0)))
+ return 0;
+
+From 6c1e4ac7b3e47db3795aecf5780244bd2d3f86a1 Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Thu, 23 Nov 2017 20:35:57 +0100
+Subject: [PATCH 249/303] bump version DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 0e38b8ced4de..a3ce57172f94 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20171120-160727
++20171123-203556
+
+From 89ee14d7bf65457e1b5e7f0f4f02d2e36dd31296 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sat, 25 Nov 2017 19:53:48 +0100
+Subject: [PATCH 250/303] print the invalid insn if invalid expression as
+ operand
+
+---
+ gcc/final.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/gcc/final.c b/gcc/final.c
+index 420ac2b08fa1..009d8eca6baf 100644
+--- gcc/final.c
++++ gcc/final.c
+@@ -4002,6 +4002,7 @@ output_addr_const (FILE *file, rtx x)
+ if (targetm.asm_out.output_addr_const_extra (file, x))
+ break;
+
++ debug_rtx(current_output_insn);
+ output_operand_lossage ("invalid expression as operand");
+ }
+ }
+
+From 6d7603c860ea47e19102eabe262c7cd34d7ab304 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sat, 25 Nov 2017 19:54:52 +0100
+Subject: [PATCH 251/303] use the default include folder (was non existant
+ os-include)
+
+---
+ gcc/config/m68k/m68kamigaos.h | 16 +---------------
+ 1 file changed, 1 insertion(+), 15 deletions(-)
+
+diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h
+index cd099997bf07..0e982c12da9c 100644
+--- gcc/config/m68k/m68kamigaos.h
++++ gcc/config/m68k/m68kamigaos.h
+@@ -686,22 +686,8 @@ amigaos_prelink_hook((const char **)(LD1_ARGV), (STRIP))
+ #undef MAX_OFILE_ALIGNMENT
+ #define MAX_OFILE_ALIGNMENT ((1 << 15)*BITS_PER_UNIT)
+
+-#if 0
+-#undef INCLUDE_DEFAULTS
+-#define INCLUDE_DEFAULTS \
+- { \
+- { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1, \
+- GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 0 }, \
+- { GCC_INCLUDE_DIR, "GCC", 0, 0 }, \
+- { CROSS_INCLUDE_DIR "/../../os-include", "GCC", 0, 0 }, \
+- { TOOL_INCLUDE_DIR "/../ndk/include", "GCC", 0, 0 }, \
+- { CROSS_INCLUDE_DIR, "GCC", 0, 0, 0 }, \
+- { 0, 0, 0, 0 } \
+- }
+-#endif
+-
+ #undef FIXED_INCLUDE_DIR
+-#define FIXED_INCLUDE_DIR CROSS_INCLUDE_DIR "/../../os-include"
++#define FIXED_INCLUDE_DIR CROSS_INCLUDE_DIR "/../../include"
+
+ // this disables tree_loop_distribute_patterns
+ #define C_COMMON_OVERRIDE_OPTIONS flag_no_builtin = 1
+
+From e25ebad9d63114a43b258f2045c646b8b090ebee Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sat, 25 Nov 2017 20:39:19 +0100
+Subject: [PATCH 252/303] fixed warnings
+
+---
+ gcc/c/c-decl.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
+index 42ebfeb9fa90..642829b828c7 100644
+--- gcc/c/c-decl.c
++++ gcc/c/c-decl.c
+@@ -4448,12 +4448,12 @@ c_decl_attributes (tree *node, tree attributes, int flags)
+ /* add an attribute to the function decl's type if there are asm register parameters. */
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ {
+- char * synthetic = "";
++ char const * synthetic = "";
+ for (tree params = TYPE_ARG_TYPES(TREE_TYPE(*node)); params; params = TREE_CHAIN(params))
+ {
+ tree asmattr = lookup_attribute("asm", TYPE_ATTRIBUTES(TREE_VALUE(params)));
+ if (asmattr)
+- synthetic = concat(synthetic, reg_names[TREE_FIXED_CST_PTR(TREE_VALUE(asmattr))->data.low], 0);
++ synthetic = concat(synthetic, reg_names[TREE_FIXED_CST_PTR(TREE_VALUE(asmattr))->data.low], NULL);
+ }
+ if (strlen(synthetic) > 0)
+ {
+
+From 6dda10eb7bc66196a2e359d87dc9c832eed982f1 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sat, 25 Nov 2017 20:40:33 +0100
+Subject: [PATCH 253/303] added checks to prevent invalid baserel insns plus
+ some converions into valid insns for better code
+
+---
+ gcc/bbb-opts.c | 16 +--
+ gcc/config/m68k/amigaos-protos.h | 3 +-
+ gcc/config/m68k/amigaos.c | 281 ++++++++++++++++++++-------------------
+ gcc/config/m68k/amigaos.h | 41 ++++--
+ gcc/config/m68k/m68k.c | 21 ++-
+ 5 files changed, 193 insertions(+), 169 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index a4fee5f446b0..2d3280230207 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -4461,19 +4461,7 @@ namespace
+ {
+ if (CONST_PLUS_PIC_REG_CONST_UNSPEC_P(XEXP(*src, 0)))
+ {
+- bool isplus = GET_CODE(*src) == PLUS;
+- rtx offset = XEXP(*src, 1);
+-
+- // unlink PLUS/MINUS
+- *src = XEXP(*src, 0);
+-
+- rtx plus = XEXP(*src, 0);
+- rtx cnst = XEXP(plus, 1);
+- rtx unspec = XEXP(cnst, 0);
+-
+- XVECEXP(unspec, 0, 0) = gen_rtx_PLUS(SImode, XVECEXP(unspec, 0, 0), gen_rtx_CONST_INT (SImode, isplus ? INTVAL(offset) : -INTVAL(offset)));
+-
+- ispicref = true;
++ amigaos_add_offset_to_symbol(src);
+ }
+ }
+ else
+@@ -4482,7 +4470,7 @@ namespace
+ if (ispicref)
+ {
+ rtx dest = SET_DEST(set);
+- if (MEM_P(dest) && GET_CODE(XEXP(dest, 0)) != PRE_DEC
++ if (MEM_P(dest) && GET_CODE(XEXP(dest, 0)) != PRE_DEC
+ )
+ {
+ // split the insn
+diff --git a/gcc/config/m68k/amigaos-protos.h b/gcc/config/m68k/amigaos-protos.h
+index 97733002f4f9..ce20a17d1840 100644
+--- gcc/config/m68k/amigaos-protos.h
++++ gcc/config/m68k/amigaos-protos.h
+@@ -34,8 +34,6 @@ extern void amigaos_init_cumulative_args (CUMULATIVE_ARGS *, tree, tree);
+ #define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
+ (amigaos_init_cumulative_args(&(CUM), (FNTYPE), (INDIRECT)))
+
+-
+-extern int amigaos_restore_a4 (void);
+ #ifdef RTX_CODE
+ extern int read_only_operand (rtx);
+ extern void amigaos_select_section (tree, int, unsigned HOST_WIDE_INT);
+@@ -56,3 +54,4 @@ extern tree amigaos_handle_decl_attribute (tree *, tree, tree, int, bool *);
+ extern tree amigaos_handle_type_attribute (tree *, tree, tree, int, bool *);
+ #endif
+
++extern void amigaos_add_offset_to_symbol(rtx *);
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index b65059edf2fa..9d2fc73d35f3 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -148,26 +148,6 @@ amigaos_encode_section_info (tree decl, rtx rtl, int first)
+ }
+ }
+
+-/* Common routine used to check if a4 should be preserved/restored. */
+-
+-int
+-amigaos_restore_a4 (void)
+- {
+- return (flag_pic >= 3 &&
+- (TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4
+- || lookup_attribute ("saveds",
+- TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))));
+- }
+-
+-void
+-amigaos_alternate_pic_setup (FILE *stream)
+- {
+- if (TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4)
+- asm_fprintf (stream, "\tjbsr %U__restore_a4\n");
+- else if (lookup_attribute ("saveds",
+- TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
+- asm_fprintf (stream, "\tlea %U__a4_init,%Ra4\n");
+- }
+
+ /* Attributes support. */
+
+@@ -242,53 +222,6 @@ amigaos_prologue_begin_hook (FILE *stream, int fsize)
+ }
+ }
+
+-void
+-amigaos_alternate_frame_setup_f (FILE *stream, int fsize)
+- {
+- if (fsize < 128)
+- asm_fprintf (stream, "\tcmpl %s,%Rsp\n"
+- "\tjcc 0f\n"
+- "\tmoveq %I%d,%Rd0\n"
+- "\tmoveq %I0,%Rd1\n"
+- "\tjbsr %U__stkext_f\n"
+- "0:\tlink %Ra5,%I%d:W\n",
+- (flag_pic == 3 ? "a4@(___stk_limit:W)" :
+- (flag_pic == 4 ? "a4@(___stk_limit:L)" :
+- "___stk_limit")),
+- fsize, -fsize);
+- else
+- asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__link_a5_d0_f\n",
+- fsize);
+- }
+-
+-void
+-amigaos_alternate_frame_setup (FILE *stream, int fsize)
+- {
+- if (!fsize)
+- asm_fprintf (stream, "\tcmpl %s,%Rsp\n"
+- "\tjcc 0f\n"
+- "\tmoveq %I0,%Rd0\n"
+- "\tmoveq %I0,%Rd1\n"
+- "\tjbsr %U__stkext_f\n"
+- "0:\n",
+- (flag_pic == 3 ? "a4@(___stk_limit:W)" :
+- (flag_pic == 4 ? "a4@(___stk_limit:L)" :
+- "___stk_limit")));
+- else if (fsize < 128)
+- asm_fprintf (stream, "\tcmpl %s,%Rsp\n"
+- "\tjcc 0f\n"
+- "\tmoveq %I%d,%Rd0\n"
+- "\tmoveq %I0,%Rd1\n"
+- "\tjbsr %U__stkext_f\n"
+- "0:\taddw %I%d,%Rsp\n",
+- (flag_pic == 3 ? "a4@(___stk_limit:W)" :
+- (flag_pic == 4 ? "a4@(___stk_limit:L)" :
+- "___stk_limit")),
+- fsize, -fsize);
+- else
+- asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__sub_d0_sp_f\n",
+- fsize);
+- }
+
+ //static rtx
+ //gen_stack_management_call (rtx stack_pointer, rtx arg, const char *func)
+@@ -676,58 +609,9 @@ amigaos_comp_type_attributes (const_tree type1, const_tree type2)
+ }
+ return 1;
+ }
+-
+-/* Return zero if the attributes on TYPE1 and TYPE2 are incompatible,
+- one if they are compatible, and two if they are nearly compatible
+- (which causes a warning to be generated). */
+-#if 0
+-static int
+-m68k_comp_type_attributes (tree type1, tree type2)
+- {
+-
+- /* Functions or methods are incompatible if they specify mutually
+- exclusive ways of passing arguments. */
+- if (TREE_CODE (type1) == FUNCTION_TYPE || TREE_CODE (type1) == METHOD_TYPE)
+- {
+- tree arg1, arg2;
+- if (!! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type1)) !=
+- !! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type2))
+- || !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1)) !=
+- !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2)))
+- return 0; /* 'regparm' and 'stkparm' are mutually exclusive. */
+-
+- arg1 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1));
+- arg2 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2));
+- if (arg1 && arg2)
+- {
+- int num1 = 0, num2 = 0;
+- if (TREE_VALUE (arg1) && TREE_CODE (TREE_VALUE (arg1)) == TREE_LIST)
+- {
+- tree numofregs = TREE_VALUE (TREE_VALUE (arg1));
+- if (numofregs)
+- num1 = TREE_INT_CST_LOW (numofregs);
+- }
+- if (TREE_VALUE (arg2) && TREE_CODE (TREE_VALUE (arg2)) == TREE_LIST)
+- {
+- tree numofregs = TREE_VALUE (TREE_VALUE (arg2));
+- if (numofregs)
+- num2 = TREE_INT_CST_LOW (numofregs);
+- }
+- if (num1 != num2)
+- return 0; /* Different numbers, or no number in one type. */
+- }
+- }
+-#ifdef TARGET_AMIGAOS
+- return amigaos_comp_type_attributes(type1, type2);
+-#else
+- return 1;
+-#endif
+- }
+-#endif
+-
+ /* end-GG-local */
+
+-/* Handle a "regparm", "stkparm" attribute;
++/* Handle a regparm, stkparm, saveds attribute;
+ arguments as in struct attribute_spec.handler. */
+ tree
+ amigaos_handle_type_attribute (tree *node, tree name, tree args, int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+@@ -915,35 +799,156 @@ amigaos_static_chain_rtx (const_tree decl, bool incoming ATTRIBUTE_UNUSED)
+ return 0;
+ }
+
+-/*
+- * decline src like:
+-(plus:SI (reg/f:SI 0 d0 [210])
+- (const:SI (minus:SI (not:SI (reg:SI 12 a4))
++/**
++ * Necessary to block some funny invalid combinations if baserel is used:
+ *
++(const:SI (minus:SI (neg:SI (reg:SI 12 a4))
++ (const:SI (plus:SI (unspec:SI [
++ (symbol_ref:SI ("xyz") <var_decl 0xffcf0000 xyz>)
++ (const_int 0 [0])
++ ] 6)
++
++(plus:SI (reg:SI 10 a2)
++ (const:SI (minus:SI (neg:SI (reg:SI 12 a4))
++ (const:SI (plus:SI (unspec:SI [
++ (symbol_ref:SI ("xyz") <var_decl 0xffcf0000 xyz>)
++ (const_int 0 [0])
++ ] 6)
++ (const_int 1234 [0xe00]))))))) xyz.c:41 465 {*lea}
++
+ */
+ bool
+-amigaos_legitimate_combined_insn (rtx_insn * insn)
++amigaos_legitimate_src (rtx src)
+ {
+- rtx set = single_set(insn);
+- if (!set)
++ if (flag_pic < 3)
+ return true;
+
+- rtx x = SET_SRC(set);
+- if (GET_CODE(x) != PLUS)
+- return true;
++ if (GET_CODE(src) == PLUS || GET_CODE(src) == MINUS)
++ {
++ rtx x = XEXP(src, 0);
++ if (CONST_PLUS_PIC_REG_CONST_UNSPEC_P(x))
++ {
++ amigaos_add_offset_to_symbol(&src);
++ return true;
++ }
+
+- x = XEXP(x, 1);
+- if (GET_CODE(x) != CONST)
+- return true;
++ return amigaos_legitimate_src(x) && amigaos_legitimate_src(XEXP(src, 1));
++ }
+
+- x = XEXP(x, 0);
+- if (GET_CODE(x) != MINUS)
+- return true;
++ if (GET_CODE(src) == CONST)
++ {
++ rtx op = XEXP(src, 0);
++ if (GET_CODE(op) == MINUS || GET_CODE(op) == PLUS)
++ {
++ rtx x = XEXP(op, 0);
++ if (GET_CODE(x) == NOT || GET_CODE(x) == NEG)
++ {
++ rtx reg = XEXP(x, 0);
++ if (!REG_P(reg))
++ return true;
+
+- x = XEXP(x, 0);
+- if (GET_CODE(x) != NOT && GET_CODE(x) != NEG)
+- return true;
++// debug_rtx(src);
++ return false;
++ }
++ }
++
++ if (GET_CODE(op) == UNSPEC)
++ {
++// debug_rtx(src);
++ return false;
++ }
++ }
+
+- x = XEXP(x, 0);
+- return !REG_P(x);
++ return true;
+ }
++
++void amigaos_add_offset_to_symbol(rtx * src)
++{
++ static char num[16];
++ bool isplus = GET_CODE(*src) == PLUS;
++ rtx offset = XEXP(*src, 1);
++ sprintf(num, "%d", (int)INTVAL(offset));
++
++ /* unlink PLUS/MINUS */
++ *src = XEXP(*src, 0);
++
++ rtx plus = XEXP(*src, 0);
++ rtx cnst = XEXP(plus, 1);
++ rtx unspec = XEXP(cnst, 0);
++ rtx sym = XVECEXP(unspec, 0, 0);
++ const char * s = XSTR(sym, 0);
++
++ /* create a new symbol containing the offset. */
++ const char * t = concat(s, isplus ? "+" : "-", num, NULL);
++ XVECEXP(unspec, 0, 0) = gen_rtx_SYMBOL_REF(Pmode, t);
++}
++
++
++void
++amigaos_restore_a4 (void)
++ {
++ if (flag_pic >= 3)
++ {
++ tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
++ tree attr = lookup_attribute ("saveds", attrs);
++ if (attr || TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4)
++ {
++ rtx a4 = gen_rtx_ASM_INPUT_loc(VOIDmode, "\tlea ___init_a4,a4", DECL_SOURCE_LOCATION (current_function_decl));
++ a4->volatil = 1;
++ emit_insn(a4);
++ }
++ }
++ }
++
++void
++amigaos_alternate_frame_setup_f (int fsize)
++ {
++#if 0
++ if (fsize < 128)
++ asm_fprintf (stream, "\tcmpl %s,%Rsp\n"
++ "\tjcc 0f\n"
++ "\tmoveq %I%d,%Rd0\n"
++ "\tmoveq %I0,%Rd1\n"
++ "\tjbsr %U__stkext_f\n"
++ "0:\tlink %Ra5,%I%d:W\n",
++ (flag_pic == 3 ? "a4@(___stk_limit:W)" :
++ (flag_pic == 4 ? "a4@(___stk_limit:L)" :
++ "___stk_limit")),
++ fsize, -fsize);
++ else
++ asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__link_a5_d0_f\n",
++ fsize);
++#endif
++ }
++
++void
++amigaos_alternate_frame_setup (int fsize)
++ {
++#if 0
++ if (!fsize)
++ asm_fprintf (stream, "\tcmpl %s,%Rsp\n"
++ "\tjcc 0f\n"
++ "\tmoveq %I0,%Rd0\n"
++ "\tmoveq %I0,%Rd1\n"
++ "\tjbsr %U__stkext_f\n"
++ "0:\n",
++ (flag_pic == 3 ? "a4@(___stk_limit:W)" :
++ (flag_pic == 4 ? "a4@(___stk_limit:L)" :
++ "___stk_limit")));
++ else if (fsize < 128)
++ asm_fprintf (stream, "\tcmpl %s,%Rsp\n"
++ "\tjcc 0f\n"
++ "\tmoveq %I%d,%Rd0\n"
++ "\tmoveq %I0,%Rd1\n"
++ "\tjbsr %U__stkext_f\n"
++ "0:\taddw %I%d,%Rsp\n",
++ (flag_pic == 3 ? "a4@(___stk_limit:W)" :
++ (flag_pic == 4 ? "a4@(___stk_limit:L)" :
++ "___stk_limit")),
++ fsize, -fsize);
++ else
++ asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__sub_d0_sp_f\n",
++ fsize);
++#endif
++ }
++
+diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h
+index 11dd88854160..fe300515fa5f 100644
+--- gcc/config/m68k/amigaos.h
++++ gcc/config/m68k/amigaos.h
+@@ -1,4 +1,7 @@
+ /* Configuration for GNU C-compiler for m68k Amiga, running AmigaOS.
++ *
++ * This file is only included and used inside m68k.c to define the target.
++ *
+ Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2003
+ Free Software Foundation, Inc.
+ Contributed by Markus M. Wild (wild@amiga.physik.unizh.ch).
+@@ -288,16 +291,6 @@ while (0)
+ #define PROLOGUE_BEGIN_HOOK(STREAM, FSIZE) \
+ (amigaos_prologue_begin_hook ((STREAM), (FSIZE)))
+
+-#define HAVE_ALTERNATE_FRAME_SETUP_F(FSIZE) TARGET_STACKEXTEND
+-
+-#define ALTERNATE_FRAME_SETUP_F(STREAM, FSIZE) \
+- (amigaos_alternate_frame_setup_f ((STREAM), (FSIZE)))
+-
+-#define HAVE_ALTERNATE_FRAME_SETUP(FSIZE) TARGET_STACKEXTEND
+-
+-#define ALTERNATE_FRAME_SETUP(STREAM, FSIZE) \
+- (amigaos_alternate_frame_setup ((STREAM), (FSIZE)))
+-
+ #define HAVE_ALTERNATE_FRAME_DESTR_F(FSIZE) \
+ (TARGET_STACKEXTEND && current_function_calls_alloca)
+
+@@ -445,6 +438,7 @@ while (0)
+ affects_type_identity } */
+ #define SUBTARGET_ATTRIBUTES \
+ { "asmregs", 0, 0, false, false, false, 0, true }, \
++ { "saveds", 0, 0, false, true, true, amigaos_handle_type_attribute, false }, \
+ { "regparm", 1, 1, false, true, true, amigaos_handle_type_attribute,\
+ true }, \
+ { "stkparm", 0, 0, false, true, true, amigaos_handle_type_attribute,\
+@@ -469,7 +463,26 @@ rtx
+ amigaos_static_chain_rtx(const_tree fntype,
+ bool incoming ATTRIBUTE_UNUSED);
+
+-#undef TARGET_LEGITIMATE_COMBINED_INSN
+-#define TARGET_LEGITIMATE_COMBINED_INSN amigaos_legitimate_combined_insn
+-bool
+-amigaos_legitimate_combined_insn (rtx_insn *insn ATTRIBUTE_UNUSED);
++
++extern bool
++amigaos_legitimate_src (rtx src);
++
++extern void
++amigaos_restore_a4 (void);
++
++extern void
++amigaos_alternate_frame_setup_f (int fsize);
++
++extern void
++amigaos_alternate_frame_setup (int fsize);
++
++
++#define HAVE_ALTERNATE_FRAME_SETUP_F(FSIZE) TARGET_STACKEXTEND
++
++#define ALTERNATE_FRAME_SETUP_F(FSIZE) \
++ (amigaos_alternate_frame_setup_f ((FSIZE)))
++
++#define HAVE_ALTERNATE_FRAME_SETUP(FSIZE) TARGET_STACKEXTEND
++
++#define ALTERNATE_FRAME_SETUP(FSIZE) \
++ (amigaos_alternate_frame_setup ((FSIZE)))
+diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
+index ed9b76caf11d..4d719a0f3680 100644
+--- gcc/config/m68k/m68k.c
++++ gcc/config/m68k/m68k.c
+@@ -1058,6 +1058,11 @@ m68k_expand_prologue (void)
+
+ if (frame_pointer_needed)
+ {
++#ifdef TARGET_AMIGA
++ if (HAVE_ALTERNATE_FRAME_SETUP_F (fsize_with_regs))
++ ALTERNATE_FRAME_SETUP_F (fsize_with_regs);
++ else
++#endif
+ if (fsize_with_regs == 0 && TUNE_68040)
+ {
+ /* On the 68040, two separate moves are faster than link.w 0. */
+@@ -1067,6 +1072,10 @@ m68k_expand_prologue (void)
+ m68k_set_frame_related (emit_move_insn (frame_pointer_rtx,
+ stack_pointer_rtx));
+ }
++#ifdef TARGET_AMIGA
++ else if (HAVE_ALTERNATE_FRAME_SETUP (fsize_with_regs))
++ ALTERNATE_FRAME_SETUP (fsize_with_regs);
++#endif
+ else if (fsize_with_regs < 0x8000 || TARGET_68020)
+ m68k_set_frame_related
+ (emit_insn (gen_link (frame_pointer_rtx,
+@@ -1168,6 +1177,10 @@ m68k_expand_prologue (void)
+ if (!TARGET_SEP_DATA
+ && crtl->uses_pic_offset_table && flag_pic < 3)
+ emit_insn (gen_load_got (pic_offset_table_rtx));
++
++#ifdef TARGET_AMIGA
++ amigaos_restore_a4 ();
++#endif
+ }
+
+ /* Return true if a simple (return) instruction is sufficient for this
+@@ -2163,6 +2176,8 @@ m68k_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
+ /* SBF: the baserel(32) const plus pic_ref, symbol is an address. */
+ if (amiga_is_const_pic_ref(x))
+ return true;
++ if (!amigaos_legitimate_src(x))
++ return false;
+ #endif
+
+ return m68k_decompose_address (mode, x, strict_p, &address);
+@@ -2185,7 +2200,11 @@ m68k_legitimate_mem_p (rtx x, struct m68k_address *address)
+ bool
+ m68k_legitimate_constant_p (machine_mode mode, rtx x)
+ {
+- return mode != XFmode && !m68k_illegitimate_symbolic_constant_p (x);
++ return mode != XFmode && !m68k_illegitimate_symbolic_constant_p (x)
++#ifdef TARGET_AMIGA
++ && amigaos_legitimate_src (x)
++#endif
++ ;
+ }
+
+ /* Return true if X matches the 'Q' constraint. It must be a memory
+
+From 06f886edaaf71078005b5a79e727c279eb3249ab Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sat, 25 Nov 2017 23:16:19 +0100
+Subject: [PATCH 254/303] fix opt_autoinc: handle nested neg/not correctly
+
+---
+ gcc/bbb-opts.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 2d3280230207..b6f630bd6522 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -850,8 +850,14 @@ insn_info::make_post_inc (int regno)
+ if (is_compare ())
+ set = SET_SRC(set);
+ rtx mem = get_dst_mem_regno () == regno ? SET_DEST(set) : SET_SRC(set);
++
+ if (src_op && get_src_mem_regno () == regno)
+- mem = XEXP(mem, 1);
++ {
++ if (src_op == NEG || src_op == NOT)
++ mem = XEXP(mem, 0);
++ else
++ mem = XEXP(mem, 1);
++ }
+
+ rtx reg = XEXP(mem, 0);
+
+
+From 6095eeeb8f75626e72e6e3f023b4bb2dfebf7b6e Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sat, 25 Nov 2017 23:17:43 +0100
+Subject: [PATCH 255/303] refs #3: correct fix for peephole optimizer
+
+---
+ gcc/config/m68k/m68k.md | 4 +++-
+ gcc/recog.c | 13 -------------
+ 2 files changed, 3 insertions(+), 14 deletions(-)
+
+diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
+index 906fde496031..7b6f69835d10 100644
+--- gcc/config/m68k/m68k.md
++++ gcc/config/m68k/m68k.md
+@@ -7204,6 +7204,7 @@
+ "operands[0] = replace_equiv_address (operands[0], stack_pointer_rtx);")
+
+ ;; Changing pea X.w into a move.l is no real win here.
++;; SBF: also disable converting pea for baserel insns!
+ (define_peephole2
+ [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
+ (match_operand:SI 0 "const_int_operand" "")))
+@@ -7213,7 +7214,8 @@
+ && !reg_mentioned_p (stack_pointer_rtx, operands[2])
+ && !(CONST_INT_P (operands[2]) && INTVAL (operands[2]) != 0
+ && IN_RANGE (INTVAL (operands[2]), -0x8000, 0x7fff)
+- && !valid_mov3q_const (INTVAL (operands[2])))"
++ && !valid_mov3q_const (INTVAL (operands[2])))
++ && !CONST_PLUS_PIC_REG_CONST_UNSPEC_P(operands[2])"
+ [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_dup 0)))
+ (set (match_dup 1) (match_dup 2))]
+ {
+diff --git a/gcc/recog.c b/gcc/recog.c
+index de2340518e52..73d1fd1b1336 100644
+--- gcc/recog.c
++++ gcc/recog.c
+@@ -3249,19 +3249,6 @@ peep2_attempt (basic_block bb, rtx_insn *insn, int match_len, rtx_insn *attempt)
+ rtx_insn *new_insn;
+ bool was_call = false;
+
+-#ifdef TARGET_AMIGA
+- /* SBF: splitting may yield invalid insns -> avoid it for the special pea insn! */
+- for (int i = 0; i <= match_len; ++i)
+- {
+- rtx_insn * insn0 = peep2_insn_data[i].insn;
+- if (!PATTERN(insn0))
+- continue;
+- rtx set0 = single_set(insn0);
+- if (set0 && CONST_PLUS_PIC_REG_CONST_UNSPEC_P(SET_SRC(set0)) && MEM_P(SET_DEST(set0)))
+- return 0;
+- }
+-#endif
+-
+ /* If we are splitting an RTX_FRAME_RELATED_P insn, do not allow it to
+ match more than one insn, or to be split into more than one insn. */
+ old_insn = peep2_insn_data[peep2_current].insn;
+
+From edcaad7b5a906f1319f99f18f36cd0a9b20ef872 Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Sat, 25 Nov 2017 23:31:57 +0100
+Subject: [PATCH 256/303] bump version DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index a3ce57172f94..4b4b584889d8 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20171123-203556
++20171125-233156
+
+From ea33fc6832c62dfda09e972a526ef2842a3efe85 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 26 Nov 2017 10:48:15 +0100
+Subject: [PATCH 257/303] fix insn scan if src auto_inc is present, destination
+ mem reg was always regarded as modified
+
+---
+ gcc/bbb-opts.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index b6f630bd6522..ee4e91a99b48 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -1059,7 +1059,13 @@ insn_info::scan_rtx (rtx x)
+ use = u;
+ myuse = mu;
+ }
++
++ // avoid side effects from myuse -> def, e.g. adding the dst reg to def by src auto inc
++ mu = myuse;
++ myuse = 0;
+ scan_rtx (SET_SRC(x));
++ myuse |= mu;
++
+ int code = GET_CODE(SET_SRC(x));
+ if (code == ASM_OPERANDS)
+ hard |= def | use;
+@@ -4181,7 +4187,7 @@ try_auto_inc (unsigned index, insn_info & ii, rtx reg)
+ if (!ii.make_post_inc (regno))
+ return 0;
+
+- log ("(i) auto_inc for %s at %d\n", reg_names[regno], index);
++ log ("(i) auto_inc for %s at %d - %d fixups\n", reg_names[regno], index, fixups.size());
+
+ // fix all offsets / adds
+ for (std::set<unsigned>::iterator k = fixups.begin (); k != fixups.end (); ++k)
+
+From 73e0e6c763bd79928606dece20538b1a65a53683 Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Sun, 26 Nov 2017 11:25:01 +0100
+Subject: [PATCH 258/303] bump version DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 4b4b584889d8..1c49eda6e46b 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20171125-233156
++20171126-112501
+
+From 28fa4c97279c23894bbabe479ec7f0675e1ac1c2 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 26 Nov 2017 12:26:06 +0100
+Subject: [PATCH 259/303] fix const_cmp_sub
+
+---
+ gcc/bbb-opts.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index ee4e91a99b48..277f130f1ef4 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -2868,7 +2868,7 @@ opt_const_cmp_to_sub (void)
+ if (GET_MODE_SIZE(i0.get_mode()) > 4)
+ continue;
+
+- if (!i0.is_dst_reg () && (!i0.is_src_const () || i0.get_src_op () == PLUS))
++ if (!i0.is_dst_reg () || !i0.is_src_const () || i0.get_src_op ())
+ continue;
+
+ if (i0.get_dst_regno () != i1.get_src_regno ())
+
+From d1a50a4116660763379610abfa3e150f1db1e874 Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Sun, 26 Nov 2017 12:53:56 +0100
+Subject: [PATCH 260/303] bump version DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 1c49eda6e46b..1f73e7437484 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20171126-112501
++20171126-125355
+
+From 18c192e42fc39de08a4f6cb6f241679b28cd5efc Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 26 Nov 2017 16:01:03 +0100
+Subject: [PATCH 261/303] improved attribute/option checking
+
+---
+ gcc/config/m68k/amigaos.c | 14 ++++++++++----
+ gcc/config/m68k/amigaos.h | 6 ++++++
+ gcc/config/m68k/amigaos.opt | 6 +++---
+ 3 files changed, 19 insertions(+), 7 deletions(-)
+
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index 9d2fc73d35f3..82dfae890f9f 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -672,6 +672,15 @@ amigaos_handle_type_attribute (tree *node, tree name, tree args, int flags ATTRI
+ }
+ else if (is_attribute_p ("saveds", name))
+ {
++ if (flag_pic < 3)
++ {
++ warning (OPT_Wattributes, "`%s' attribute is only usable with fbaserel", IDENTIFIER_POINTER(name));
++ }
++ else
++ if (flag_resident)
++ {
++ error ("`saveds' can't be used with resident!\n");
++ }
+ }
+ }
+ else
+@@ -762,10 +771,7 @@ read_only_operand (rtx operand)
+ rtx
+ amigaos_struct_value_rtx (tree fntype, int incoming ATTRIBUTE_UNUSED)
+ {
+-// if (fntype && aggregate_value_p (TREE_TYPE(fntype), fntype))
+ return gen_rtx_REG (Pmode, M68K_STRUCT_VALUE_REGNUM);
+-
+-// return 0;
+ }
+
+ rtx
+@@ -887,7 +893,7 @@ void amigaos_add_offset_to_symbol(rtx * src)
+ void
+ amigaos_restore_a4 (void)
+ {
+- if (flag_pic >= 3)
++ if (flag_pic >= 3 && !flag_resident)
+ {
+ tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
+ tree attr = lookup_attribute ("saveds", attrs);
+diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h
+index fe300515fa5f..9f166d6f57c2 100644
+--- gcc/config/m68k/amigaos.h
++++ gcc/config/m68k/amigaos.h
+@@ -427,6 +427,12 @@ extern tree amigaos_handle_type_attribute(tree *, tree, tree, int, bool*);
+ #define SUBTARGET_OVERRIDE_OPTIONS \
+ do \
+ { \
++ if (flag_resident) \
++ { \
++ if (flag_pic) \
++ error ("-fbaserel and -resident are mutual exclusiv\n"); \
++ flag_pic = flag_resident; \
++ } \
+ if (!TARGET_68020 && flag_pic==4) \
+ error ("-fbaserel32 is not supported on the 68000 or 68010\n"); \
+ if (amigaos_regparm > 0 && amigaos_regparm > AMIGAOS_MAX_REGPARM) \
+diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt
+index d87f884f06b3..07406d27a777 100644
+--- gcc/config/m68k/amigaos.opt
++++ gcc/config/m68k/amigaos.opt
+@@ -32,11 +32,11 @@ Target Report Var(flag_pic,4)
+ data is addressed relative to a4 with 32 bit offsets
+
+ resident
+-Target Common Report Var(flag_pic,3)
++Target Common Report Var(flag_resident,3)
+ data is addressed relative to a4, linked as resident
+
+ resident32
+-Target Common Report Var(flag_pic,4)
++Target Common Report Var(flag_resident,4)
+ data is addressed relative to a4 with 32 bit offsets, linked as resident
+
+ mcrt=
+@@ -60,4 +60,4 @@ s a strcpy optimization
+ v be verbose
+ V be very verbose
+ x dump insns
+-Default: -fbbb=+
++Default: -fbbb=+ which yields -fbbb=abcefimprs
+
+From c14a11d08caac02a69c6a7eb76e867586113aad7 Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Sun, 26 Nov 2017 16:28:46 +0100
+Subject: [PATCH 262/303] bump version DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 1f73e7437484..216c38355e67 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20171126-125355
++20171126-162846
+
+From 9809cd847fa66de483a6994bb8ae37e1a014abea Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 27 Nov 2017 12:33:29 +0100
+Subject: [PATCH 263/303] refs #4 - use correct name: ___a4_init
+
+---
+ gcc/config/m68k/amigaos.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index 82dfae890f9f..de2e2999eb60 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -899,7 +899,7 @@ amigaos_restore_a4 (void)
+ tree attr = lookup_attribute ("saveds", attrs);
+ if (attr || TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4)
+ {
+- rtx a4 = gen_rtx_ASM_INPUT_loc(VOIDmode, "\tlea ___init_a4,a4", DECL_SOURCE_LOCATION (current_function_decl));
++ rtx a4 = gen_rtx_ASM_INPUT_loc(VOIDmode, "\tlea ___a4_init,a4", DECL_SOURCE_LOCATION (current_function_decl));
+ a4->volatil = 1;
+ emit_insn(a4);
+ }
+
+From 486fefde971da0f1a5fb28f791b940ab7801912b Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Mon, 27 Nov 2017 12:59:17 +0100
+Subject: [PATCH 264/303] bump version DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 216c38355e67..ce0da3dfd125 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20171126-162846
++20171127-125916
+
+From 9147ce3cfcd7cf9a6eaa3e5793ae43fc7791c9ed Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 29 Nov 2017 19:26:05 +0100
+Subject: [PATCH 265/303] fix opt_cmp_sub, prepare support for chip attribute,
+ changes to baserel handling
+
+---
+ gcc/bbb-opts.c | 54 +++++++++------------------
+ gcc/config/m68k/amigaos-protos.h | 2 -
+ gcc/config/m68k/amigaos.c | 80 +++++++++++++++++++++++++++-------------
+ gcc/config/m68k/amigaos.h | 7 ++++
+ gcc/config/m68k/m68k.c | 13 ++++++-
+ gcc/passes.c | 7 +++-
+ 6 files changed, 96 insertions(+), 67 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 277f130f1ef4..4525f77acc2a 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -177,7 +177,7 @@ class track_var
+
+ /* only keep common values in both sides. */
+ void
+- merge (track_var * o, unsigned at)
++ merge (track_var * o, unsigned )
+ {
+ for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+ {
+@@ -2732,44 +2732,29 @@ opt_commute_add_move (void)
+
+ for (unsigned index = 0; index + 1 < infos.size (); ++index)
+ {
+- rtx_insn * insn = infos[index].get_insn ();
+- rtx set = single_set (insn);
+- if (!set)
+- continue;
+-
+- rtx reg1dst = SET_DEST(set);
+- if (!REG_P(reg1dst))
++ insn_info & ii = infos[index];
++ if (ii.get_dst_regno() < 8 || ii.get_dst_regno() > 15 || ii.get_src_op() != PLUS || ii.get_src_regno() == ii.get_dst_regno() || !ii.get_src_intval())
+ continue;
+
+- rtx plus = SET_SRC(set);
+- if (GET_CODE(plus) != PLUS)
+- continue;
++ insn_info & jj = infos[index + 1];
+
+- rtx reg1src = XEXP(plus, 0);
+- if (!REG_P(reg1src) || reg1src == reg1dst)
++ if (!jj.get_dst_mem_reg() || jj.get_dst_mem_regno() != ii.get_src_regno()
++ || jj.get_src_regno() == ii.get_dst_regno()
++ || GET_MODE_SIZE(jj.get_mode()) != ii.get_src_intval())
+ continue;
+
+- rtx cnst = XEXP(plus, 1);
+- if (!CONST_INT_P(cnst))
+- continue;
++ rtx_insn * insn = ii.get_insn ();
+
+- rtx_insn * next = infos[index + 1].get_insn ();
++ rtx_insn * next = jj.get_insn ();
+ rtx set2 = single_set (next);
+- if (!set2)
+- continue;
+-
+ rtx dst = SET_DEST(set2);
+- if (!MEM_P(dst) || GET_MODE_SIZE(GET_MODE(dst)) != INTVAL(cnst))
+- continue;
+-
+- rtx memreg = XEXP(dst, 0);
+- if (!REG_P(memreg) || REGNO(memreg) != REGNO(reg1src))
++ if (!MEM_P(dst))
+ continue;
+
+- rtx pinc = gen_rtx_POST_INC(GET_MODE(dst), reg1dst);
++ rtx pinc = gen_rtx_POST_INC(GET_MODE(dst), ii.get_dst_reg());
+ rtx newmem = replace_equiv_address_nv (dst, pinc);
+
+- rtx_insn * newinsn = make_insn_raw (gen_rtx_SET(reg1dst, reg1src));
++ rtx_insn * newinsn = make_insn_raw (gen_rtx_SET(ii.get_dst_reg(), ii.get_src_reg()));
+
+ if (!insn_invalid_p (newinsn, 1) && validate_change (next, &SET_DEST(set2), newmem, 1) && apply_change_group ())
+ {
+@@ -2779,7 +2764,7 @@ opt_commute_add_move (void)
+
+ insn = emit_insn_before (newinsn, next);
+
+- add_reg_note (next, REG_INC, reg1dst);
++ add_reg_note (next, REG_INC, ii.get_dst_reg());
+
+ ++change_count;
+ }
+@@ -4470,12 +4455,7 @@ namespace
+ bool ispicref = false;
+ // fix add PLUS/MINUS into the unspec offset
+ if (GET_CODE(*src) == PLUS || GET_CODE(*src) == MINUS)
+- {
+- if (CONST_PLUS_PIC_REG_CONST_UNSPEC_P(XEXP(*src, 0)))
+- {
+- amigaos_add_offset_to_symbol(src);
+- }
+- }
++ ispicref = CONST_PLUS_PIC_REG_CONST_UNSPEC_P(XEXP(*src, 0));
+ else
+ ispicref = CONST_PLUS_PIC_REG_CONST_UNSPEC_P(*src);
+
+@@ -4489,10 +4469,12 @@ namespace
+ rtx reg = gen_reg_rtx (Pmode);
+
+ rtx pat0 = gen_rtx_SET(reg, *src);
+- rtx_insn * n0 = emit_insn_before(pat0, insn);
++ //rtx_insn * n0 =
++ emit_insn_before(pat0, insn);
+
+ rtx pat1 = gen_rtx_SET(dest, reg);
+- rtx_insn * n1 = emit_insn_before(pat1, insn);
++ //rtx_insn * n1 =
++ emit_insn_before(pat1, insn);
+
+ SET_INSN_DELETED(insn);
+ }
+diff --git a/gcc/config/m68k/amigaos-protos.h b/gcc/config/m68k/amigaos-protos.h
+index ce20a17d1840..e5cd6e950b52 100644
+--- gcc/config/m68k/amigaos-protos.h
++++ gcc/config/m68k/amigaos-protos.h
+@@ -53,5 +53,3 @@ extern struct rtx_def *amigaos_function_arg (CUMULATIVE_ARGS *, enum machine_mod
+ extern tree amigaos_handle_decl_attribute (tree *, tree, tree, int, bool *);
+ extern tree amigaos_handle_type_attribute (tree *, tree, tree, int, bool *);
+ #endif
+-
+-extern void amigaos_add_offset_to_symbol(rtx *);
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index de2e2999eb60..ba8a5d757d21 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -682,10 +682,21 @@ amigaos_handle_type_attribute (tree *node, tree name, tree args, int flags ATTRI
+ error ("`saveds' can't be used with resident!\n");
+ }
+ }
++ else
++ {
++ warning (OPT_Wattributes, "`%s' attribute only applies to data", IDENTIFIER_POINTER(name));
++ }
+ }
+ else
+ {
+- warning (OPT_Wattributes, "`%s' attribute only applies to functions", IDENTIFIER_POINTER(name));
++ if (is_attribute_p ("chip", name))
++ {
++ // OK
++ }
++ else
++ {
++ warning (OPT_Wattributes, "`%s' attribute only applies to functions", IDENTIFIER_POINTER(name));
++ }
+ }
+ return NULL_TREE ;
+ }
+@@ -695,6 +706,46 @@ amigaos_handle_type_attribute (tree *node, tree name, tree args, int flags ATTRI
+ return NULL_TREE ;
+ }
+
++#define AMIGA_CHIP_SECTION_NAME ".datachip"
++
++void
++amiga_insert_attribute (tree decl, tree * attr)
++{
++ if (!*attr)
++ return;
++
++ tree name = TREE_PURPOSE(*attr);
++
++ if (is_attribute_p("chip", name))
++ {
++ if (!TREE_TYPE(decl) == VAR_DECL)
++ {
++ error ("`chip' attribute can only be specified for variables");
++ return;
++ }
++
++ if (! TREE_STATIC (decl) && ! DECL_EXTERNAL (decl))
++ {
++ error ("`chip' attribute cannot be specified for local variables");
++ return;
++ }
++ /* The decl may have already been given a section attribute from
++ a previous declaration. Ensure they match. */
++ if (DECL_SECTION_NAME (decl) == NULL)
++ warning (OPT_Wattributes, "`%s' attribute is not yet supported", IDENTIFIER_POINTER(name));
++// set_decl_section_name(decl, AMIGA_CHIP_SECTION_NAME);
++ else if (strcmp (DECL_SECTION_NAME (decl), AMIGA_CHIP_SECTION_NAME) )
++ {
++ error_at (DECL_SOURCE_LOCATION(decl),
++ "`chip' attribute conflicts with previous declaration");
++ }
++ }
++ else
++ {
++// warning (OPT_Wattributes, "`%s' attribute unknown", IDENTIFIER_POINTER(name));
++ }
++}
++
+ extern bool
+ m68k_rtx_costs (rtx, machine_mode, int, int, int *, bool);
+
+@@ -832,11 +883,10 @@ amigaos_legitimate_src (rtx src)
+ if (GET_CODE(src) == PLUS || GET_CODE(src) == MINUS)
+ {
+ rtx x = XEXP(src, 0);
++
++ /** handled in print_operand_address(...) */
+ if (CONST_PLUS_PIC_REG_CONST_UNSPEC_P(x))
+- {
+- amigaos_add_offset_to_symbol(&src);
+ return true;
+- }
+
+ return amigaos_legitimate_src(x) && amigaos_legitimate_src(XEXP(src, 1));
+ }
+@@ -868,28 +918,6 @@ amigaos_legitimate_src (rtx src)
+ return true;
+ }
+
+-void amigaos_add_offset_to_symbol(rtx * src)
+-{
+- static char num[16];
+- bool isplus = GET_CODE(*src) == PLUS;
+- rtx offset = XEXP(*src, 1);
+- sprintf(num, "%d", (int)INTVAL(offset));
+-
+- /* unlink PLUS/MINUS */
+- *src = XEXP(*src, 0);
+-
+- rtx plus = XEXP(*src, 0);
+- rtx cnst = XEXP(plus, 1);
+- rtx unspec = XEXP(cnst, 0);
+- rtx sym = XVECEXP(unspec, 0, 0);
+- const char * s = XSTR(sym, 0);
+-
+- /* create a new symbol containing the offset. */
+- const char * t = concat(s, isplus ? "+" : "-", num, NULL);
+- XVECEXP(unspec, 0, 0) = gen_rtx_SYMBOL_REF(Pmode, t);
+-}
+-
+-
+ void
+ amigaos_restore_a4 (void)
+ {
+diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h
+index 9f166d6f57c2..723c36969ad1 100644
+--- gcc/config/m68k/amigaos.h
++++ gcc/config/m68k/amigaos.h
+@@ -444,6 +444,7 @@ while (0)
+ affects_type_identity } */
+ #define SUBTARGET_ATTRIBUTES \
+ { "asmregs", 0, 0, false, false, false, 0, true }, \
++ { "chip", 0, 0, false, true, false, amigaos_handle_type_attribute, false }, \
+ { "saveds", 0, 0, false, true, true, amigaos_handle_type_attribute, false }, \
+ { "regparm", 1, 1, false, true, true, amigaos_handle_type_attribute,\
+ true }, \
+@@ -492,3 +493,9 @@ amigaos_alternate_frame_setup (int fsize);
+
+ #define ALTERNATE_FRAME_SETUP(FSIZE) \
+ (amigaos_alternate_frame_setup ((FSIZE)))
++
++#undef TARGET_INSERT_ATTRIBUTES
++#define TARGET_INSERT_ATTRIBUTES amiga_insert_attribute
++
++void
++amiga_insert_attribute (tree decl, tree * attr);
+diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
+index 4d719a0f3680..f5daa0cbcc26 100644
+--- gcc/config/m68k/m68k.c
++++ gcc/config/m68k/m68k.c
+@@ -4835,6 +4835,14 @@ print_operand_address (FILE *file, rtx addr)
+ print_operand_address(file, XEXP(addr, 0));
+ return;
+ }
++ if (GET_CODE(addr) == PLUS && CONST_PLUS_PIC_REG_CONST_UNSPEC_P(XEXP(addr, 0)))
++ {
++ fprintf (file, "%d+", (int) INTVAL (XEXP(addr, 1)));
++ print_operand_address(file, XEXP(XEXP(addr, 0),0));
++ return;
++ }
++
++
+ if (symbolic_operand(addr, VOIDmode))
+ {
+ memset (&address, 0, sizeof (address));
+@@ -4843,7 +4851,10 @@ print_operand_address (FILE *file, rtx addr)
+ else
+ #endif
+ if (!m68k_decompose_address (QImode, addr, true, &address))
+- gcc_unreachable ();
++ {
++ debug_rtx(addr);
++ gcc_unreachable ();
++ }
+
+ if (address.code == PRE_DEC)
+ fprintf (file, MOTOROLA ? "-(%s)" : "%s@-",
+diff --git a/gcc/passes.c b/gcc/passes.c
+index 407160f4e4d6..b216ee028245 100644
+--- gcc/passes.c
++++ gcc/passes.c
+@@ -2276,7 +2276,8 @@ void dump_insns(char const * name)
+ for (insn = get_insns(); insn; insn = next)
+ {
+ next = NEXT_INSN(insn);
+-#if 1
++ debug_rtx(insn);
++#if 0
+ if (NONJUMP_INSN_P (insn))
+ {
+ rtx set= single_set (insn);
+@@ -2290,6 +2291,7 @@ void dump_insns(char const * name)
+ }
+ }
+
++
+ /* Execute PASS. */
+
+ bool
+@@ -2299,7 +2301,8 @@ execute_one_pass (opt_pass *pass)
+
+ bool gate_status;
+
+-// dump_insns(pass->name);
++ if (string_bbb_opts && strchr (string_bbb_opts, 'Y'))
++ dump_insns(pass->name);
+
+ /* IPA passes are executed on whole program, so cfun should be NULL.
+ Other passes need function context set. */
+
+From 4a14629a3a38f9c4d043813eb36247a5a0b3adc7 Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Wed, 29 Nov 2017 19:55:45 +0100
+Subject: [PATCH 266/303] bump version DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index ce0da3dfd125..4aee726e0fe2 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20171127-125916
++20171129-195545
+
+From e2608938b1210496cf528a280030a5906a6991e5 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 1 Dec 2017 20:06:38 +0100
+Subject: [PATCH 267/303] fix opt_auto_inc again
+
+---
+ gcc/bbb-opts.c | 38 +++++++++++++++++++++-----------------
+ 1 file changed, 21 insertions(+), 17 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 4525f77acc2a..7c8fc94ed8a6 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -177,7 +177,7 @@ class track_var
+
+ /* only keep common values in both sides. */
+ void
+- merge (track_var * o, unsigned )
++ merge (track_var * o, unsigned)
+ {
+ for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+ {
+@@ -928,7 +928,7 @@ insn_info::auto_inc_fixup (int regno, int size)
+ SET_SRC(set) = XEXP(src, 0);
+ }
+ else
+- XEXP(src, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(src, 1)), src_intval -= size);
++ XEXP(src, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(src, 1)), src_intval -= size);
+ }
+ else if (get_src_mem_regno () == regno)
+ {
+@@ -2733,14 +2733,14 @@ opt_commute_add_move (void)
+ for (unsigned index = 0; index + 1 < infos.size (); ++index)
+ {
+ insn_info & ii = infos[index];
+- if (ii.get_dst_regno() < 8 || ii.get_dst_regno() > 15 || ii.get_src_op() != PLUS || ii.get_src_regno() == ii.get_dst_regno() || !ii.get_src_intval())
++ if (ii.get_dst_regno () < 8 || ii.get_dst_regno () > 15 || ii.get_src_op () != PLUS
++ || ii.get_src_regno () == ii.get_dst_regno () || !ii.get_src_intval ())
+ continue;
+
+ insn_info & jj = infos[index + 1];
+
+- if (!jj.get_dst_mem_reg() || jj.get_dst_mem_regno() != ii.get_src_regno()
+- || jj.get_src_regno() == ii.get_dst_regno()
+- || GET_MODE_SIZE(jj.get_mode()) != ii.get_src_intval())
++ if (!jj.get_dst_mem_reg () || jj.get_dst_mem_regno () != ii.get_src_regno ()
++ || jj.get_src_regno () == ii.get_dst_regno () || GET_MODE_SIZE(jj.get_mode()) != ii.get_src_intval ())
+ continue;
+
+ rtx_insn * insn = ii.get_insn ();
+@@ -2751,10 +2751,10 @@ opt_commute_add_move (void)
+ if (!MEM_P(dst))
+ continue;
+
+- rtx pinc = gen_rtx_POST_INC(GET_MODE(dst), ii.get_dst_reg());
++ rtx pinc = gen_rtx_POST_INC(GET_MODE(dst), ii.get_dst_reg ());
+ rtx newmem = replace_equiv_address_nv (dst, pinc);
+
+- rtx_insn * newinsn = make_insn_raw (gen_rtx_SET(ii.get_dst_reg(), ii.get_src_reg()));
++ rtx_insn * newinsn = make_insn_raw (gen_rtx_SET(ii.get_dst_reg (), ii.get_src_reg ()));
+
+ if (!insn_invalid_p (newinsn, 1) && validate_change (next, &SET_DEST(set2), newmem, 1) && apply_change_group ())
+ {
+@@ -2764,7 +2764,7 @@ opt_commute_add_move (void)
+
+ insn = emit_insn_before (newinsn, next);
+
+- add_reg_note (next, REG_INC, ii.get_dst_reg());
++ add_reg_note (next, REG_INC, ii.get_dst_reg ());
+
+ ++change_count;
+ }
+@@ -4136,6 +4136,9 @@ try_auto_inc (unsigned index, insn_info & ii, rtx reg)
+ bool fix = false;
+ if (jj.get_src_mem_regno () == regno)
+ {
++ if (jj.get_dst_regno () == regno)
++ return 0;
++
+ if (jj.get_src_mem_addr () < size)
+ return 0;
+
+@@ -4146,6 +4149,9 @@ try_auto_inc (unsigned index, insn_info & ii, rtx reg)
+ }
+ if (jj.get_dst_mem_regno () == regno)
+ {
++ if (jj.get_src_regno () == regno)
++ return 0;
++
+ if (jj.get_dst_mem_addr () < size)
+ return 0;
+
+@@ -4172,7 +4178,7 @@ try_auto_inc (unsigned index, insn_info & ii, rtx reg)
+ if (!ii.make_post_inc (regno))
+ return 0;
+
+- log ("(i) auto_inc for %s at %d - %d fixups\n", reg_names[regno], index, fixups.size());
++ log ("(i) auto_inc for %s at %d - %d fixups\n", reg_names[regno], index, fixups.size ());
+
+ // fix all offsets / adds
+ for (std::set<unsigned>::iterator k = fixups.begin (); k != fixups.end (); ++k)
+@@ -4220,13 +4226,12 @@ opt_autoinc ()
+ // if ((ii.get_myuse () & 0xff0000))
+ // continue;
+
+- rtx reg = 0;
+ if (ii.is_src_mem () && ii.get_src_mem_regno () >= 8 && !ii.get_src_mem_addr () && !ii.get_src_autoinc ()
+ && ii.get_src_mem_regno () != ii.get_dst_mem_regno () && ii.get_src_mem_regno () != ii.get_dst_regno ())
+ change_count += try_auto_inc (index, ii, ii.get_src_mem_reg ());
+
+- if (!reg && ii.is_dst_mem () && ii.get_dst_mem_regno () >= 8 && !ii.get_dst_intval () && !ii.get_dst_autoinc ()
+- && ii.get_src_mem_regno () != ii.get_dst_mem_regno ())
++ if (ii.is_dst_mem () && ii.get_dst_mem_regno () >= 8 && !ii.get_dst_intval () && !ii.get_dst_autoinc ()
++ && ii.get_src_mem_regno () != ii.get_dst_mem_regno () && ii.get_src_regno () != ii.get_dst_mem_regno ())
+ change_count += try_auto_inc (index, ii, ii.get_dst_mem_reg ());
+
+ }
+@@ -4462,19 +4467,18 @@ namespace
+ if (ispicref)
+ {
+ rtx dest = SET_DEST(set);
+- if (MEM_P(dest) && GET_CODE(XEXP(dest, 0)) != PRE_DEC
+- )
++ if (MEM_P(dest) && GET_CODE(XEXP(dest, 0)) != PRE_DEC)
+ {
+ // split the insn
+ rtx reg = gen_reg_rtx (Pmode);
+
+ rtx pat0 = gen_rtx_SET(reg, *src);
+ //rtx_insn * n0 =
+- emit_insn_before(pat0, insn);
++ emit_insn_before (pat0, insn);
+
+ rtx pat1 = gen_rtx_SET(dest, reg);
+ //rtx_insn * n1 =
+- emit_insn_before(pat1, insn);
++ emit_insn_before (pat1, insn);
+
+ SET_INSN_DELETED(insn);
+ }
+
+From 34ff5f41808c0f6eef3ea36cb6592f696b568e0f Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Fri, 1 Dec 2017 20:33:49 +0100
+Subject: [PATCH 268/303] bump version DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 4aee726e0fe2..5ca5b245f261 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20171129-195545
++20171201-203349
+
+From 865d8c2a52ee44716669dc3353d5cd10f2cc2836 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 3 Dec 2017 23:15:02 +0100
+Subject: [PATCH 269/303] fix opt_auto_inc if set is 0
+
+---
+ gcc/bbb-opts.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 7c8fc94ed8a6..757cc93dda94 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -845,6 +845,9 @@ insn_info::make_post_inc (int regno)
+
+ // convert into POST_INC
+ rtx set0 = single_set (new_insn);
++ if (!set0)
++ return false;
++
+ rtx set = set0;
+
+ if (is_compare ())
+
+From d565753800ac3d71d6367a3c5f7db440b2068e48 Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Sun, 3 Dec 2017 23:43:43 +0100
+Subject: [PATCH 270/303] bump version DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 5ca5b245f261..e90d802ff727 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20171201-203349
++20171203-234342
+
+From 7018006ca506699e3241293713bca07d71bea88c Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 10 Dec 2017 16:00:32 +0100
+Subject: [PATCH 271/303] more baserel fixes + cleanup= less changes to
+ original code
+
+---
+ gcc/bbb-opts.c | 395 +++++++++++++++++++++++++++++------------
+ gcc/config/m68k/amigaos.c | 76 ++++++--
+ gcc/config/m68k/constraints.md | 8 +-
+ gcc/config/m68k/m68k.c | 35 +++-
+ gcc/config/m68k/m68k.md | 16 +-
+ gcc/config/m68k/m68kamigaos.h | 19 +-
+ gcc/final.c | 6 +
+ gcc/passes.c | 2 +-
+ 8 files changed, 390 insertions(+), 167 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 757cc93dda94..dca287181b3a 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -70,12 +70,20 @@
+ #include "tree-pass.h"
+ #include "conditions.h"
+ #include "langhooks.h"
++#include <vector>
++#include <set>
++#include <map>
+
+ int be_very_verbose;
+ bool be_verbose;
+
+ extern struct lang_hooks lang_hooks;
+
++static void
++update_insn_infos (void);
++static unsigned
++track_regs ();
++
+ /* Lookup of the current function name. */
+ extern tree current_function_decl;
+ static tree last_function_decl;
+@@ -116,63 +124,210 @@ enum proepis
+ IN_CODE, IN_PROLOGUE, IN_EPILOGUE, IN_EPILOGUE_PARALLEL_POP
+ };
+
++/**
++ * What's needed to track values?
++ */
+ class track_var
+ {
+- unsigned * indexes;
+- rtx * values;
+- unsigned * versions;
++ rtx value[FIRST_PSEUDO_REGISTER];
++ unsigned mask[FIRST_PSEUDO_REGISTER];
++
++ bool
++ extend (rtx * z, unsigned * mask, machine_mode dstMode, rtx x)
++ {
++ switch (GET_CODE(x))
++ {
++ case CONST_INT:
++ case CONST_FIXED:
++ case CONST_DOUBLE:
++ case SYMBOL_REF:
++ case LABEL_REF:
++ /* these can be used directly. */
++ *z = x;
++ return true;
++
++ case REG:
++ {
++ rtx v = value[REGNO(x)];
++ /* try to expand the register. */
++ if (v)
++ {
++ if (GET_MODE(v) != VOIDmode && dstMode != GET_MODE(v))
++ return false;
++
++ *mask |= mask[REGNO(x)];
++ *z = value[REGNO(x)];
++ return true;
++ }
++
++ /* store the reg otherwise. */
++ *mask |= (1 << REGNO(x));
++ *z = x;
++ return true;
++ }
++ case PLUS:
++ case MINUS:
++ // handle only in combination with const
++ {
++ rtx y = XEXP(x, 0);
++ if (GET_CODE(y) != SYMBOL_REF && GET_CODE(y) == LABEL_REF && amiga_is_const_pic_ref(y))
++ return false;
++
++ if (GET_CODE(x) == PLUS) // create an own plus to be able to modify the constant offset (later).
++ *z = gen_rtx_PLUS(GET_MODE(x), y, XEXP(x, 1));
++ else
++ *z = gen_rtx_MINUS(GET_MODE(x), y, XEXP(x, 1));
++ return true;
++ }
++
++ /* memory reads. */
++ case MEM:
++ {
++ rtx m = XEXP(x, 0);
++ switch (GET_CODE(m))
++ {
++ case SYMBOL_REF:
++ case LABEL_REF:
++ /* these can be used directly. */
++ *z = x;
++ return true;
++
++ case REG:
++ if (!extend (&m, mask, dstMode, m))
++ return false;
++
++ *z = gen_rtx_MEM (GET_MODE(x), m);
++ return true;
++
++ case PLUS:
++ case MINUS:
++ // handle only in combination with const
++ {
++ rtx y = XEXP(m, 0);
++ if (!REG_P(
++ y) && GET_CODE(y) != SYMBOL_REF && GET_CODE(y) == LABEL_REF && amiga_is_const_pic_ref(y))
++ return false;
++
++ if (REG_P(y))
++ if (!extend (&y, mask, dstMode, y))
++ return false;
++
++ if (GET_CODE(x) == PLUS) // create an own plus to be able to modify the constant offset (later).
++ m = gen_rtx_PLUS(GET_MODE(m), y, XEXP(m, 1));
++ else
++ m = gen_rtx_MINUS(GET_MODE(m), y, XEXP(m, 1));
++
++ *z = gen_rtx_MEM (GET_MODE(x), m);
++ return true;
++ }
++ }
++ return false;
++ }
++
++ default:
++ return false;
++ }
++ }
+
+ public:
+- track_var (track_var const * o = 0) :
+- indexes ((unsigned *) xcalloc (FIRST_PSEUDO_REGISTER, sizeof(unsigned))), values (
+- (rtx *) xcalloc (FIRST_PSEUDO_REGISTER, sizeof(rtx))), versions (
+- (unsigned *) xcalloc (FIRST_PSEUDO_REGISTER, sizeof(unsigned)))
++ track_var (track_var const * o = 0)
+ {
+ if (o)
+ assign (o);
++ else
++ for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
++ {
++ value[i] = 0;
++ mask[i] = 0;
++ }
++ }
++
++ rtx
++ get (unsigned regno)
++ {
++ if (regno >= FIRST_PSEUDO_REGISTER)
++ return 0;
++
++ return value[regno];
+ }
+
+ void
+- set (unsigned regno, unsigned index, rtx rtx, unsigned ver)
++ set (machine_mode mode, unsigned regno, rtx x, unsigned index)
+ {
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ return;
+
+- indexes[regno] = index;
+- values[regno] = rtx;
+- versions[regno] = ver;
++ if (!extend (&value[regno], &mask[regno], mode, x))
++ {
++ clear (regno, index);
++ }
+ }
+
+- unsigned
+- get_index (unsigned regno) const
++ bool
++ equals (unsigned regno, rtx x)
+ {
+ if (regno >= FIRST_PSEUDO_REGISTER)
+- return 0;
+- return indexes[regno];
++ return false;
++
++ if (x == 0 || value[regno] == 0)
++ return false;
++
++ rtx z = 0;
++ unsigned m = 0;
++ if (!extend (&z, &m, GET_MODE(x), x))
++ return false;
++
++ return rtx_equal_p (z, value[regno]);
+ }
+
+- rtx
+- get_value (unsigned regno) const
++ void
++ clear (unsigned regno, unsigned index)
+ {
+ if (regno >= FIRST_PSEUDO_REGISTER)
+- return 0;
+- return values[regno];
++ return;
++
++ value[regno] = gen_rtx_CONST_INT (VOIDmode, 0x100000000000000LL | ((long long int) (regno) << 32) | index);
++ mask[regno] = FIRST_PSEUDO_REGISTER;
+ }
+
+- unsigned
+- get_version (unsigned regno) const
++ void
++ clear_aftercall (unsigned index)
+ {
+- if (regno >= FIRST_PSEUDO_REGISTER)
+- return 0;
+- return versions[regno];
++ for (int i = 2; i < FIRST_PSEUDO_REGISTER; ++i)
++ {
++ if (mask[i])
++ {
++ value[i] = 0;
++ mask[i] = 0;
++ }
++ }
++ clear (0, index);
++ clear (1, index);
++ clear (8, index);
++ clear (9, index);
+ }
+
+ void
+- assign (track_var const * o) const
++ clear_for_mask (unsigned def, unsigned index)
+ {
+- memcpy (indexes, o->indexes, FIRST_PSEUDO_REGISTER * sizeof(unsigned));
+- memcpy (values, o->values, FIRST_PSEUDO_REGISTER * sizeof(rtx));
+- memcpy (versions, o->versions, FIRST_PSEUDO_REGISTER * sizeof(unsigned));
++ if (!def)
++ return;
++ for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
++ {
++ // register changed or used somehow
++ if ((1 << regno) & def)
++ clear (regno, index);
++ }
++ }
++
++ void
++ assign (track_var const * o)
++ {
++ for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
++ {
++ value[i] = o->value[i];
++ mask[i] = o->mask[i];
++ }
+ }
+
+ /* only keep common values in both sides. */
+@@ -181,8 +336,11 @@ class track_var
+ {
+ for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+ {
+- if (versions[i] != o->versions[0] || !rtx_equal_p (values[i], o->values[i]))
+- values[i] = o->values[i] = 0;
++ if (!rtx_equal_p (value[i], o->value[i]))
++ {
++ value[i] = o->value[i] = 0;
++ mask[i] = mask[i] = 0;
++ }
+ }
+ }
+
+@@ -192,9 +350,8 @@ class track_var
+ {
+ for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+ {
+- if (versions[i] != o->versions[0] || !rtx_equal_p (values[i], o->values[i]))
+- if (values[i])
+- return false;
++ if (!rtx_equal_p (value[i], o->value[i]))
++ return false;
+ }
+ return true;
+ }
+@@ -931,7 +1088,7 @@ insn_info::auto_inc_fixup (int regno, int size)
+ SET_SRC(set) = XEXP(src, 0);
+ }
+ else
+- XEXP(src, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(src, 1)), src_intval -= size);
++ XEXP(src, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(src, 1)), src_intval -= size);
+ }
+ else if (get_src_mem_regno () == regno)
+ {
+@@ -1367,11 +1524,11 @@ update_insn2index ()
+ static void
+ update_label2jump ()
+ {
++ update_insn2index ();
++
+ for (unsigned index = 0; index < infos.size (); ++index)
+ {
+ insn_info & ii = infos[index];
+- insn2info.insert (std::make_pair (ii.get_insn (), &ii));
+-
+ if (ii.is_label ())
+ for (l2j_iterator i = label2jump.find (ii.get_insn ()->u2.insn_uid), k = i;
+ i != label2jump.end () && i->first == k->first; ++i)
+@@ -1598,12 +1755,47 @@ is_reg_dead (unsigned regno, unsigned _pos)
+ return true;
+ }
+
++bool dump_reg_track;
++void
++append_reg_cache (FILE * f, rtx_insn * insn)
++{
++ i2i_iterator i = insn2info.find (insn);
++ if (i == insn2info.end ())
++ return;
++
++ insn_info & jj = *i->second;
++ unsigned index = jj.get_index ();
++ if (index + 1 < infos.size ())
++ ++index;
++ insn_info & ii = infos[index];
++
++ track_var * track = ii.get_track_var ();
++ if (track == 0)
++ return;
++
++ fprintf (f, "\n");
++
++ for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
++ {
++ rtx v = track->get (regno);
++ if (v == 0)
++ continue;
++
++// if (GET_CODE(v) == CONST_INT && GET_MODE(v) == VOIDmode)
++// continue;
++
++ fprintf (f, "%s=", reg_names[regno]);
++
++ print_inline_rtx (f, v, 12);
++ fprintf (f, "\n");
++ }
++}
++
+ /* helper stuff to enhance the asm output. */
+ int my_flag_regusage;
+ void
+ append_reg_usage (FILE * f, rtx_insn * insn)
+ {
+-
+ i2i_iterator i = insn2info.find (insn);
+ if (i == insn2info.end ())
+ return;
+@@ -3635,53 +3827,48 @@ opt_shrink_stack_frame (void)
+
+ /* Update the insn_infos to 'know' the value for each register.
+ *
+- * atm only assignments to registers are optimized.
++ * assignments to registers are optimized by knowing the value. If the same value is assigned, omit that insn.
+ *
+- * We track register aliases:
++ * I'm tracking
+ *
+- * ;10
+- * move.l 4(a0),d0
++ * rtx - the value
+ *
+- * ;15
+- * move.l d0,d1
++ * mask - the referenced registers in the value, 0 means that rtx is const, with baserel a4 is not tracked
+ *
++ * if there is a value for the referenced register(s), the value is extended
+ *
+- * ;18
+- * move.l d1,d2
++ * e.g.
+ *
+- * - results into d0 is an alias for d1 (and vice versa).
+- * - to identify if a register is still changed, we also track the line where it was assigned.
+- * - in addition to register aliases memory reads are tracked too for normal memory access (e.g. no auto inc)
+- * but not if the memory read is marked as volatile
++ * ; line 2
++ * move.l 12(a7),a0
+ *
+- * E.g.
++ * -> rtx = mem(plus(a7, 12)); 0x8000
+ *
+- * d0[10]: 4(a0)[10]
+- * d1[15]: d0[10]
+- * d2[18]: d1[15]
++ * ; line 10
++ * move.l 4(a0),d0
+ *
+- * with that information we know that d2[18] also contains 4(a0)[10]
++ * -> rtx = mem(plus(mem(plus(a7, 12)), 4)); 0x8000; extended with value from a0, thus a7 is used only
+ *
+- * info to track per register:
+- * line index where the value was assigned
+- * rtx which was assigned - or null if not a usable rtx
+- * reg line index - if rtx is a register
++ * ;15
++ * lea _label,a1
+ *
+- * for each assignment which is not to a register the rtx are scanned and set to null on match
++ * -> rtx = symbol_ref(_label) ; 0x0000 == const
+ *
+ * on jumps the current state is duplicated and merged at the given label
+ *
+ * on merge only identical info is kept, rest is discarded
+ *
+- * for each insn first the track info for all defined regs is discarded before the new one is set.
++ * for each insn for all defined regs the value and mask is discarded before a new value is set.
++ *
++ * for each insn which is writing to memory, all non const values are discarded.
+ *
+ *
+- * after the track info is complete, each insn is evaluated agains the track info.
++ * after the track info is complete, each insn setting a register is evaluated against the track info.
+ *
+ * now redundant loads are found and eliminated
+- * also unused assignments are found an eliminated
+ *
+ */
++
+ static unsigned
+ track_regs ()
+ {
+@@ -3733,26 +3920,19 @@ track_regs ()
+ ii.get_track_var ()->assign (track);
+
+ int dregno = ii.get_dst_regno ();
++ track->clear (dregno, index);
++
+ unsigned def = ii.get_def () & 0xffffff;
+- if (def)
+- {
+- for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
+- {
+- // register changed or used somehow
+- if (((1 << regno) & def)
+- || (track->get_index (regno) && (infos[track->get_index (regno)].get_myuse () & def)))
+- track->set (regno, index, 0, index);
+- }
+- // clear on self update
+- if (def & ii.get_myuse ())
+- track->set (dregno, index, 0, index);
+- }
++ track->clear_for_mask (def, index);
+
+ if (ii.is_compare ())
+ continue;
+
+ if (ii.is_call ())
+- continue;
++ {
++ track->clear_aftercall (index);
++ continue;
++ }
+
+ rtx set = single_set (ii.get_insn ());
+
+@@ -3786,21 +3966,7 @@ track_regs ()
+ if (ii.is_src_mem () && src->volatil)
+ continue;
+
+- // add the entry - determine the version - use 0 for const values
+- unsigned version;
+- if (GET_CODE(src) != CONST_INT && GET_CODE(src) != CONST_FIXED && GET_CODE(src) != CONST_DOUBLE)
+- {
+- if (ii.get_src_regno () >= 0)
+- version = track->get_index (ii.get_src_regno ());
+- else if (ii.get_src_mem_regno () >= 0)
+- version = track->get_index (ii.get_src_mem_regno ());
+- else
+- version = index;
+- }
+- else
+- version = 0;
+-
+- track->set (dregno, index, src, version);
++ track->set (ii.get_mode (), dregno, src, index);
+ }
+ delete track;
+ }
+@@ -3843,35 +4009,23 @@ opt_elim_dead_assign (int blocked_regno)
+ {
+ track_var * track = ii.get_track_var ();
+
+-// if (ii.get_src_regno() == 8 && ii.get_dst_regno() == 7)
+-// printf("%d: move %d,%d: v=%d (%d->%d), i=%d (%d->%d)\n", index, ii.get_src_regno(), ii.get_dst_regno(),
+-// track->get_version(ii.get_src_regno()), infos[track->get_version(ii.get_src_regno())].get_src_regno(), infos[track->get_version(ii.get_src_regno())].get_dst_regno(),
+-// track->get_index(ii.get_dst_regno()), infos[track->get_index(ii.get_dst_regno())].get_src_regno(), infos[track->get_index(ii.get_dst_regno())].get_dst_regno());
+-
+ rtx src = SET_SRC(set);
+- if (rtx_equal_p (track->get_value (ii.get_dst_regno ()), src))
++ if (track->equals (ii.get_dst_regno (), src))
+ {
+- if ((REG_P(src) && track->get_version (ii.get_dst_regno ()) == track->get_index (ii.get_src_regno ()))
+- || !REG_P(src))
+- {
+- log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]);
+- SET_INSN_DELETED(insn);
+- ++change_count;
+- continue;
+- }
++ log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]);
++ SET_INSN_DELETED(insn);
++ ++change_count;
++ continue;
+ }
+- // check reverse assignment
+- if (REG_P(src))
++
++ if (ii.get_src_reg () && track->equals (ii.get_src_regno (), SET_DEST(set)))
+ {
+- if (REG_P(src) && rtx_equal_p (track->get_value (ii.get_src_regno ()), SET_DEST(set))
+- && track->get_version (ii.get_src_regno ()) == track->get_index (ii.get_dst_regno ()))
+- {
+- log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]);
+- SET_INSN_DELETED(insn);
+- ++change_count;
+- continue;
+- }
++ log ("(e) %d: eliminate redundant reverse load to %s\n", index, reg_names[ii.get_dst_regno ()]);
++ SET_INSN_DELETED(insn);
++ ++change_count;
++ continue;
+ }
++
+ }
+ }
+ return change_count;
+@@ -4300,6 +4454,7 @@ namespace
+ unsigned
+ pass_bbb_optimizations::execute_bbb_optimizations (void)
+ {
++ dump_reg_track = strchr (string_bbb_opts, 'R') != 0;
+ be_very_verbose = strchr (string_bbb_opts, 'V') != 0;
+ be_verbose = strchr (string_bbb_opts, 'v') != 0;
+ if (be_verbose && be_very_verbose)
+@@ -4380,6 +4535,12 @@ namespace
+ if (strchr (string_bbb_opts, 'X') || strchr (string_bbb_opts, 'x'))
+ dump_insns ("bbb", strchr (string_bbb_opts, 'X'));
+
++ if (dump_reg_track)
++ {
++ update_insns ();
++ track_regs ();
++ }
++
+ return r;
+ }
+
+@@ -4463,9 +4624,9 @@ namespace
+ bool ispicref = false;
+ // fix add PLUS/MINUS into the unspec offset
+ if (GET_CODE(*src) == PLUS || GET_CODE(*src) == MINUS)
+- ispicref = CONST_PLUS_PIC_REG_CONST_UNSPEC_P(XEXP(*src, 0));
++ ispicref = amiga_is_const_pic_ref(XEXP(*src, 0));
+ else
+- ispicref = CONST_PLUS_PIC_REG_CONST_UNSPEC_P(*src);
++ ispicref = amiga_is_const_pic_ref(*src);
+
+ if (ispicref)
+ {
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index ba8a5d757d21..298bcb18300c 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -793,17 +793,47 @@ amiga_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_U
+ /**
+ * Does x reference the pic_reg and is const or plus?
+ */
++static int
++_amiga_is_const_pic_ref (const_rtx x)
++{
++ if (GET_CODE(x) == PLUS || GET_CODE(x) == MINUS)
++ {
++ if (GET_CODE(XEXP(x, 1)) == CONST_INT)
++ return _amiga_is_const_pic_ref(XEXP(x, 0));
++ return false;
++ }
++
++ if (GET_CODE(x) == CONST)
++ x = XEXP(x, 0);
++ if (GET_CODE(x) != PLUS)
++ return false;
++
++ const_rtx reg = XEXP(x, 0);
++ if (!REG_P(reg) && REGNO(reg) != PIC_REG)
++ return false;
++
++ const_rtx unspec = XEXP(x, 1);
++ while (GET_CODE(unspec) == PLUS || GET_CODE(unspec) == CONST)
++ unspec = XEXP(unspec, 0);
++
++ if (GET_CODE(unspec) != UNSPEC)
++ return false;
++
++ return true;
++}
++
+ int
+-amiga_is_const_pic_ref (const_rtx x)
++amiga_is_const_pic_ref (const_rtx cnst)
+ {
+- const_rtx y = x;
+ if (flag_pic < 3)
+- return false;
+- while (GET_CODE(y) == CONST || GET_CODE(y) == PLUS)
+- y = XEXP(y, 0);
+- return (x != y && REG_P(y) && REGNO(y) == PIC_REG);
++ return true;
++ int r = _amiga_is_const_pic_ref (cnst);
++// fprintf(stderr, r ? "valid pic: " : "invalid pic: ");
++// debug_rtx(cnst);
++ return r;
+ }
+
++
+ /* Does operand (which is a symbolic_operand) live in text space? If
+ so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true.
+
+@@ -880,15 +910,27 @@ amigaos_legitimate_src (rtx src)
+ if (flag_pic < 3)
+ return true;
+
++ if (MEM_P(src))
++ {
++ rtx x = XEXP(src, 0);
++ if (GET_CODE(x) == PLUS || GET_CODE(x) == MINUS) {
++ if (amiga_is_const_pic_ref(XEXP(x, 0))
++ || amiga_is_const_pic_ref(XEXP(x, 1)))
++ return false;
++ }
++ return true;
++ }
++
+ if (GET_CODE(src) == PLUS || GET_CODE(src) == MINUS)
+ {
+ rtx x = XEXP(src, 0);
++ rtx y = XEXP(src, 1);
+
+ /** handled in print_operand_address(...) */
+- if (CONST_PLUS_PIC_REG_CONST_UNSPEC_P(x))
+- return true;
++ if (amiga_is_const_pic_ref(x))
++ return GET_CODE(y) == CONST_INT;
+
+- return amigaos_legitimate_src(x) && amigaos_legitimate_src(XEXP(src, 1));
++ return amigaos_legitimate_src(x) && amigaos_legitimate_src(y) && !amiga_is_const_pic_ref(y);
+ }
+
+ if (GET_CODE(src) == CONST)
+@@ -903,16 +945,12 @@ amigaos_legitimate_src (rtx src)
+ if (!REG_P(reg))
+ return true;
+
+-// debug_rtx(src);
+ return false;
+ }
+ }
+
+ if (GET_CODE(op) == UNSPEC)
+- {
+-// debug_rtx(src);
+- return false;
+- }
++ return false;
+ }
+
+ return true;
+@@ -986,3 +1024,13 @@ amigaos_alternate_frame_setup (int fsize)
+ #endif
+ }
+
++#if 0
++extern bool debug_recog(char const * txt, int which_alternative, int n, rtx * operands)
++{
++ fprintf(stderr, "%s: %d ", txt, which_alternative);
++ for (int i = 0; i < n; ++i)
++ print_rtl(stderr, operands[i]);
++ fprintf(stderr, "\n--\n");
++ return true;
++}
++#endif
+diff --git a/gcc/config/m68k/constraints.md b/gcc/config/m68k/constraints.md
+index 0d9b1b69ab18..1223852570c1 100644
+--- gcc/config/m68k/constraints.md
++++ gcc/config/m68k/constraints.md
+@@ -1,5 +1,5 @@
+ ;; Constraint definitions for m68k
+-;; Copyright (C) 2007-2016 Free Software Foundation, Inc.
++;; Copyright (C) 2007-2015 Free Software Foundation, Inc.
+
+ ;; This file is part of GCC.
+
+@@ -97,12 +97,6 @@
+ (match_test "!TARGET_PCREL")
+ (match_test "!flag_pic || LEGITIMATE_PIC_OPERAND_P (op)")))
+
+-(define_constraint "t"
+- "Used for operands that satisfy 's' without PIC stuff, when -mpcrel is not in effect."
+- (and (match_code "symbol_ref,label_ref,const")
+- (match_test "!TARGET_PCREL")
+- (match_test "!flag_pic || !CONST_PLUS_PIC_REG_CONST_UNSPEC_P(op)")))
+-
+ (define_memory_constraint "Q"
+ "Means address register indirect addressing mode."
+ (and (match_code "mem")
+diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
+index f5daa0cbcc26..a655ed8476bb 100644
+--- gcc/config/m68k/m68k.c
++++ gcc/config/m68k/m68k.c
+@@ -2176,8 +2176,10 @@ m68k_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
+ /* SBF: the baserel(32) const plus pic_ref, symbol is an address. */
+ if (amiga_is_const_pic_ref(x))
+ return true;
++
+ if (!amigaos_legitimate_src(x))
+ return false;
++
+ #endif
+
+ return m68k_decompose_address (mode, x, strict_p, &address);
+@@ -2530,7 +2532,7 @@ legitimize_pic_address (rtx orig, machine_mode mode ATTRIBUTE_UNUSED,
+ /* SBF: Does the symbol use common or bss and qualifies for pic_reg?
+ * Do not ref to .text via pic_reg!
+ */
+- if (!SYMBOL_REF_FUNCTION_P(orig) && decl && (DECL_COMMON (decl) || bss_initializer_p (decl)))
++ if (GET_CODE (orig) == SYMBOL_REF && !SYMBOL_REF_FUNCTION_P(orig) && decl && (DECL_COMMON (decl) || bss_initializer_p (decl)))
+ {
+ /* SBF: unfortunately using the wrapped symbol without MEM does not work.
+ * The pic_ref reference gets decomposed and leads to no working code.
+@@ -4603,7 +4605,7 @@ print_operand (FILE *file, rtx op, int letter)
+ && INTVAL (XEXP (op, 0)) >= -0x8000)
+ #ifdef TARGET_AMIGA
+ /* SBF: Do not append some 'l' with baserel(32). */
+- && !CONST_PLUS_PIC_REG_CONST_UNSPEC_P(XEXP(op, 0))
++ && !amiga_is_const_pic_ref(XEXP(op, 0))
+ #endif
+ )
+ fprintf (file, MOTOROLA ? ".l" : ":l");
+@@ -4830,12 +4832,35 @@ print_operand_address (FILE *file, rtx addr)
+ /*
+ * SBF: remove the const wrapper.
+ */
+- if (CONST_PLUS_PIC_REG_CONST_UNSPEC_P(addr))
++ if (amiga_is_const_pic_ref(addr))
+ {
+- print_operand_address(file, XEXP(addr, 0));
++ /* handle (plus (unspec ) (const_int) */
++ rtx *x = &addr;
++ while (GET_CODE(*x) != PLUS)
++ x = &XEXP(*x, 0);
++
++ x = &XEXP(*x, 1); // CONST
++ if (GET_CODE(*x) == CONST)
++ x = &XEXP(*x, 0);
++
++ /* if there is a plus - swap it.
++ * we want n+symbol:W (not symbol:W+n)
++ */
++ if (GET_CODE(*x) == PLUS)
++ {
++ rtx plus = *x;
++ fprintf (file, "%d+", (int) INTVAL (XEXP(plus, 1)));
++
++ *x = XEXP(plus, 0);
++ print_operand_address(file, XEXP(addr, 0));
++ *x = plus;
++ }
++ else
++ print_operand_address(file, XEXP(addr, 0));
++
+ return;
+ }
+- if (GET_CODE(addr) == PLUS && CONST_PLUS_PIC_REG_CONST_UNSPEC_P(XEXP(addr, 0)))
++ if (GET_CODE(addr) == PLUS && amiga_is_const_pic_ref(XEXP(addr, 0)))
+ {
+ fprintf (file, "%d+", (int) INTVAL (XEXP(addr, 1)));
+ print_operand_address(file, XEXP(XEXP(addr, 0),0));
+diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
+index 7b6f69835d10..05ef02027f01 100644
+--- gcc/config/m68k/m68k.md
++++ gcc/config/m68k/m68k.md
+@@ -500,7 +500,7 @@
+ [(set (cc0)
+ (compare (match_operand:SI 0 "nonimmediate_operand" "rKT,rKs,mr,ma,>")
+ (match_operand:SI 1 "general_operand" "mr,ma,KTr,Ksr,>")))]
+- "!TARGET_COLDFIRE && (flag_pic < 3 || GET_CODE(operands[1]) != CONST || GET_CODE(XEXP(operands[1], 0)) != PLUS || !REG_P(XEXP(XEXP(operands[1], 0), 0)) || REGNO(XEXP(XEXP(operands[1], 0), 0)) != PIC_REG)"
++ "!TARGET_COLDFIRE"
+ {
+ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+ return "cmpm%.l %1,%0";
+@@ -955,8 +955,8 @@
+ (define_insn "*movsi_m68k"
+ ;; Notes: make sure no alternative allows g vs g.
+ ;; We don't allow f-regs since fixed point cannot go in them.
+- [(set (match_operand:SI 0 "nonimmediate_operand" "=g,a,d,a<")
+- (match_operand:SI 1 "general_src_operand" "damSnt,T,n,i"))]
++ [(set (match_operand:SI 0 "nonimmediate_operand" "=g,d,a<")
++ (match_operand:SI 1 "general_src_operand" "damSnT,n,i"))]
+ "!TARGET_COLDFIRE && reload_completed"
+ {
+ return output_move_simode (operands);
+@@ -966,8 +966,8 @@
+ ;; force integer constants in range for a moveq to be reloaded
+ ;; if they are headed for memory.
+ (define_insn "*movsi_m68k2"
+- [(set (match_operand:SI 0 "nonimmediate_operand" "=g,a,d,a<")
+- (match_operand:SI 1 "general_src_operand" "damSKt,T,n,i"))]
++ [(set (match_operand:SI 0 "nonimmediate_operand" "=g,d,a<")
++ (match_operand:SI 1 "general_src_operand" "damSKT,n,i"))]
+
+ "!TARGET_COLDFIRE"
+ {
+@@ -2468,7 +2468,7 @@
+ (define_insn "*addsi3_internal"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=m,?a,?a,d,a")
+ (plus:SI (match_operand:SI 1 "general_operand" "%0,a,rJK,0,0")
+- (match_operand:SI 2 "general_src_operand" "dIKLT,rJK,a,mSrIKLt,mSrIKLt")))]
++ (match_operand:SI 2 "general_src_operand" "dIKLT,rJK,a,mSrIKLT,mSrIKLs")))]
+
+
+ "! TARGET_COLDFIRE"
+@@ -7090,8 +7090,6 @@
+ operands[1] = gen_rtx_REG (Pmode, PIC_REG);
+ return MOTOROLA ? "move.l %?(%1),%0" : "movel %1@(%?), %0";
+ }
+- else if (TARGET_AMIGAOS)
+- return "lea (%%pc, __GLOBAL_OFFSET_TABLE_), %0";
+ else if (MOTOROLA)
+ {
+ if (TARGET_COLDFIRE)
+@@ -7215,7 +7213,7 @@
+ && !(CONST_INT_P (operands[2]) && INTVAL (operands[2]) != 0
+ && IN_RANGE (INTVAL (operands[2]), -0x8000, 0x7fff)
+ && !valid_mov3q_const (INTVAL (operands[2])))
+- && !CONST_PLUS_PIC_REG_CONST_UNSPEC_P(operands[2])"
++ && !amiga_is_const_pic_ref(operands[2])"
+ [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_dup 0)))
+ (set (match_dup 1) (match_dup 2))]
+ {
+diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h
+index 0e982c12da9c..43ffcd0add39 100644
+--- gcc/config/m68k/m68kamigaos.h
++++ gcc/config/m68k/m68kamigaos.h
+@@ -700,18 +700,17 @@ extern int amiga_is_const_pic_ref(const_rtx x);
+ ((GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \
+ || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST \
+ || GET_CODE (X) == HIGH \
+- ) && !amiga_is_const_pic_ref(X))
++ ))
++
+
+
+ /* Given that symbolic_operand(X), return TRUE if no special
+ base relative relocation is necessary */
+
+-#define LEGITIMATE_BASEREL_OPERAND_P(X) \
+- (flag_pic >= 3 && read_only_operand (X))
+-
+ #undef LEGITIMATE_PIC_OPERAND_P
+ #define LEGITIMATE_PIC_OPERAND_P(X) ( \
+- ! symbolic_operand (X, VOIDmode) || LEGITIMATE_BASEREL_OPERAND_P (X))
++ ! symbolic_operand (X, VOIDmode) && \
++ ! amiga_is_const_pic_ref(X))
+
+ // (GET_CODE(X) == CONST && (GET_CODE(XEXP(X, 0)) == SYMBOL_REF || GET_CODE(XEXP(X, 0)) == LABEL_REF) && !CONSTANT_POOL_ADDRESS_P (XEXP(X, 0))) ||
+
+@@ -742,12 +741,4 @@ extern int amiga_is_const_pic_ref(const_rtx x);
+ extern int
+ amigaos_function_arg_reg(unsigned regno);
+
+-/* SBF: macro to test for const via pic_reg. */
+-#define CONST_PLUS_PIC_REG_CONST_UNSPEC_P(x) \
+- (GET_CODE(x) == CONST \
+- && GET_CODE(XEXP(x, 0)) == PLUS \
+- && REG_P(XEXP(XEXP(x, 0), 0)) \
+- && REGNO(XEXP(XEXP(x, 0), 0)) == PIC_REG \
+- && GET_CODE(XEXP(XEXP(x, 0), 1)) == CONST \
+- && GET_CODE(XEXP(XEXP(XEXP(x, 0), 1), 0)) == UNSPEC \
+- )
++//extern bool debug_recog(char const * txt, int which_alternative, int n, rtx * operands);
+diff --git a/gcc/final.c b/gcc/final.c
+index 009d8eca6baf..fa8b2964a40d 100644
+--- gcc/final.c
++++ gcc/final.c
+@@ -3626,6 +3626,10 @@ output_asm_insn (const char *templ, rtx *operands)
+ {
+ extern bool be_very_verbose;
+ extern void append_reg_usage(FILE *, rtx_insn *);
++
++ extern bool dump_reg_track;
++ void append_reg_cache (FILE * f, rtx_insn * insn);
++
+ const char *p;
+ int c;
+ #ifdef ASSEMBLER_DIALECT
+@@ -3784,6 +3788,8 @@ output_asm_insn (const char *templ, rtx *operands)
+
+ if (be_very_verbose)
+ append_reg_usage(asm_out_file, current_insn);
++ if (dump_reg_track)
++ append_reg_cache(asm_out_file, current_insn);
+
+ /* Write out the variable names for operands, if we know them. */
+ if (flag_verbose_asm)
+diff --git a/gcc/passes.c b/gcc/passes.c
+index b216ee028245..1d53bb23b1b0 100644
+--- gcc/passes.c
++++ gcc/passes.c
+@@ -2284,7 +2284,7 @@ void dump_insns(char const * name)
+ if (!set)
+ continue;
+
+- if (CONST_PLUS_PIC_REG_CONST_UNSPEC_P(SET_SRC(set)) && MEM_P(SET_DEST(set)))
++ if (amiga_is_const_pic_ref(SET_SRC(set)) && MEM_P(SET_DEST(set)))
+ debug_rtx(insn);
+ }
+ #endif
+
+From 219a2963be09c8bf789e875cefc55520a195d44a Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 10 Dec 2017 21:04:22 +0100
+Subject: [PATCH 272/303] fix flag_pic handling
+
+---
+ gcc/config/m68k/amigaos.c | 2 +-
+ gcc/config/m68k/m68k.c | 2 ++
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index 298bcb18300c..1fe7d09b0142 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -826,7 +826,7 @@ int
+ amiga_is_const_pic_ref (const_rtx cnst)
+ {
+ if (flag_pic < 3)
+- return true;
++ return false;
+ int r = _amiga_is_const_pic_ref (cnst);
+ // fprintf(stderr, r ? "valid pic: " : "invalid pic: ");
+ // debug_rtx(cnst);
+diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
+index a655ed8476bb..0a67f320bc1d 100644
+--- gcc/config/m68k/m68k.c
++++ gcc/config/m68k/m68k.c
+@@ -2173,6 +2173,8 @@ m68k_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
+ struct m68k_address address;
+
+ #ifdef TARGET_AMIGA
++ if (MEM_P(x))
++ return false;
+ /* SBF: the baserel(32) const plus pic_ref, symbol is an address. */
+ if (amiga_is_const_pic_ref(x))
+ return true;
+
+From 4c1164092dea34f47a66606c8962bc9b053ed650 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sun, 10 Dec 2017 21:47:42 +0100
+Subject: [PATCH 273/303] fix mode handling in register tracking
+
+---
+ gcc/bbb-opts.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index dca287181b3a..32ef3ddde253 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -142,6 +142,8 @@ class track_var
+ case CONST_DOUBLE:
+ case SYMBOL_REF:
+ case LABEL_REF:
++ if (GET_MODE(x) != dstMode)
++ return false;
+ /* these can be used directly. */
+ *z = x;
+ return true;
+@@ -152,7 +154,7 @@ class track_var
+ /* try to expand the register. */
+ if (v)
+ {
+- if (GET_MODE(v) != VOIDmode && dstMode != GET_MODE(v))
++ if (dstMode != GET_MODE(v))
+ return false;
+
+ *mask |= mask[REGNO(x)];
+@@ -286,7 +288,7 @@ class track_var
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ return;
+
+- value[regno] = gen_rtx_CONST_INT (VOIDmode, 0x100000000000000LL | ((long long int) (regno) << 32) | index);
++ value[regno] = gen_rtx_CONST_INT (SImode, 0x100000000000000LL | ((long long int) (regno) << 32) | index);
+ mask[regno] = FIRST_PSEUDO_REGISTER;
+ }
+
+
+From 50f74c0693d7b285ec06e3d0b12d0acb5a966a2d Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 11 Dec 2017 09:18:02 +0100
+Subject: [PATCH 274/303] fix compare handling in register tracking
+
+---
+ gcc/bbb-opts.c | 14 ++++++--------
+ 1 file changed, 6 insertions(+), 8 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 32ef3ddde253..faf69739db8d 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -142,8 +142,6 @@ class track_var
+ case CONST_DOUBLE:
+ case SYMBOL_REF:
+ case LABEL_REF:
+- if (GET_MODE(x) != dstMode)
+- return false;
+ /* these can be used directly. */
+ *z = x;
+ return true;
+@@ -154,7 +152,7 @@ class track_var
+ /* try to expand the register. */
+ if (v)
+ {
+- if (dstMode != GET_MODE(v))
++ if (dstMode != GET_MODE(v) && GET_CODE(v) != CONST_INT)
+ return false;
+
+ *mask |= mask[REGNO(x)];
+@@ -289,7 +287,7 @@ class track_var
+ return;
+
+ value[regno] = gen_rtx_CONST_INT (SImode, 0x100000000000000LL | ((long long int) (regno) << 32) | index);
+- mask[regno] = FIRST_PSEUDO_REGISTER;
++ mask[regno] = 1<<FIRST_PSEUDO_REGISTER;
+ }
+
+ void
+@@ -297,7 +295,7 @@ class track_var
+ {
+ for (int i = 2; i < FIRST_PSEUDO_REGISTER; ++i)
+ {
+- if (mask[i])
++ if (mask[i] && mask[i] < 1<<FIRST_PSEUDO_REGISTER)
+ {
+ value[i] = 0;
+ mask[i] = 0;
+@@ -3921,15 +3919,15 @@ track_regs ()
+ ii.mark_visited ();
+ ii.get_track_var ()->assign (track);
+
++ if (ii.is_compare ())
++ continue;
++
+ int dregno = ii.get_dst_regno ();
+ track->clear (dregno, index);
+
+ unsigned def = ii.get_def () & 0xffffff;
+ track->clear_for_mask (def, index);
+
+- if (ii.is_compare ())
+- continue;
+-
+ if (ii.is_call ())
+ {
+ track->clear_aftercall (index);
+
+From ed451fd6c28cdbca52f247c6719996a3b612c207 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 11 Dec 2017 10:13:33 +0100
+Subject: [PATCH 275/303] fix mode handling b/w/l
+
+---
+ gcc/bbb-opts.c | 30 +++++++++++++++++-------------
+ 1 file changed, 17 insertions(+), 13 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index faf69739db8d..676201619747 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -149,20 +149,24 @@ class track_var
+ case REG:
+ {
+ rtx v = value[REGNO(x)];
++ unsigned mr = mask[REGNO(x)];
+ /* try to expand the register. */
+ if (v)
+ {
+- if (dstMode != GET_MODE(v) && GET_CODE(v) != CONST_INT)
++ if (dstMode != GET_MODE(v) && (GET_CODE(v) != CONST_INT || mr == (1<<FIRST_PSEUDO_REGISTER)))
+ return false;
+
+- *mask |= mask[REGNO(x)];
+- *z = value[REGNO(x)];
++ *mask |= mr;
++ *z = v;
+ return true;
+ }
+
+ /* store the reg otherwise. */
+ *mask |= (1 << REGNO(x));
+- *z = x;
++ if (GET_MODE(x) == dstMode)
++ *z = x;
++ else
++ *z = gen_rtx_REG(dstMode, REGNO(x));
+ return true;
+ }
+ case PLUS:
+@@ -259,7 +263,7 @@ class track_var
+
+ if (!extend (&value[regno], &mask[regno], mode, x))
+ {
+- clear (regno, index);
++ clear (mode, regno, index);
+ }
+ }
+
+@@ -281,12 +285,12 @@ class track_var
+ }
+
+ void
+- clear (unsigned regno, unsigned index)
++ clear (machine_mode mode, unsigned regno, unsigned index)
+ {
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ return;
+
+- value[regno] = gen_rtx_CONST_INT (SImode, 0x100000000000000LL | ((long long int) (regno) << 32) | index);
++ value[regno] = gen_rtx_CONST_INT (mode, 0x100000000000000LL | ((long long int) (regno) << 32) | index);
+ mask[regno] = 1<<FIRST_PSEUDO_REGISTER;
+ }
+
+@@ -301,10 +305,10 @@ class track_var
+ mask[i] = 0;
+ }
+ }
+- clear (0, index);
+- clear (1, index);
+- clear (8, index);
+- clear (9, index);
++ clear (SImode, 0, index);
++ clear (SImode, 1, index);
++ clear (SImode, 8, index);
++ clear (SImode, 9, index);
+ }
+
+ void
+@@ -316,7 +320,7 @@ class track_var
+ {
+ // register changed or used somehow
+ if ((1 << regno) & def)
+- clear (regno, index);
++ clear (SImode, regno, index);
+ }
+ }
+
+@@ -3923,7 +3927,7 @@ track_regs ()
+ continue;
+
+ int dregno = ii.get_dst_regno ();
+- track->clear (dregno, index);
++ track->clear (ii.get_mode(), dregno, index);
+
+ unsigned def = ii.get_def () & 0xffffff;
+ track->clear_for_mask (def, index);
+
+From dfad986c2f43b33e98dbc2b70a4058b8cf771a37 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 11 Dec 2017 10:52:23 +0100
+Subject: [PATCH 276/303] fix mode handling
+
+---
+ gcc/bbb-opts.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 676201619747..e56e38ba73e0 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -290,7 +290,7 @@ class track_var
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ return;
+
+- value[regno] = gen_rtx_CONST_INT (mode, 0x100000000000000LL | ((long long int) (regno) << 32) | index);
++ value[regno] = gen_rtx_raw_CONST_INT (mode, 0x100000000000000LL | ((long long int) (regno) << 32) | index);
+ mask[regno] = 1<<FIRST_PSEUDO_REGISTER;
+ }
+
+
+From 4e20f18ef084146dab3f58a73e4959c2ee85980f Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 11 Dec 2017 11:29:39 +0100
+Subject: [PATCH 277/303] treat SFmode as SImode for normal regs
+
+---
+ gcc/bbb-opts.c | 26 +++++++++++++++-----------
+ 1 file changed, 15 insertions(+), 11 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index e56e38ba73e0..f54fb54d4405 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -153,7 +153,7 @@ class track_var
+ /* try to expand the register. */
+ if (v)
+ {
+- if (dstMode != GET_MODE(v) && (GET_CODE(v) != CONST_INT || mr == (1<<FIRST_PSEUDO_REGISTER)))
++ if (dstMode != GET_MODE(v) && (GET_CODE(v) != CONST_INT || mr == (1 << FIRST_PSEUDO_REGISTER)))
+ return false;
+
+ *mask |= mr;
+@@ -166,7 +166,7 @@ class track_var
+ if (GET_MODE(x) == dstMode)
+ *z = x;
+ else
+- *z = gen_rtx_REG(dstMode, REGNO(x));
++ *z = gen_rtx_REG (dstMode, REGNO(x));
+ return true;
+ }
+ case PLUS:
+@@ -174,7 +174,7 @@ class track_var
+ // handle only in combination with const
+ {
+ rtx y = XEXP(x, 0);
+- if (GET_CODE(y) != SYMBOL_REF && GET_CODE(y) == LABEL_REF && amiga_is_const_pic_ref(y))
++ if (GET_CODE(y) != SYMBOL_REF && GET_CODE(y) == LABEL_REF && amiga_is_const_pic_ref (y))
+ return false;
+
+ if (GET_CODE(x) == PLUS) // create an own plus to be able to modify the constant offset (later).
+@@ -208,8 +208,7 @@ class track_var
+ // handle only in combination with const
+ {
+ rtx y = XEXP(m, 0);
+- if (!REG_P(
+- y) && GET_CODE(y) != SYMBOL_REF && GET_CODE(y) == LABEL_REF && amiga_is_const_pic_ref(y))
++ if (!REG_P(y) && GET_CODE(y) != SYMBOL_REF && GET_CODE(y) == LABEL_REF && amiga_is_const_pic_ref (y))
+ return false;
+
+ if (REG_P(y))
+@@ -261,6 +260,9 @@ class track_var
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ return;
+
++ if (mode == SFmode && regno < 16)
++ mode = SImode;
++
+ if (!extend (&value[regno], &mask[regno], mode, x))
+ {
+ clear (mode, regno, index);
+@@ -290,8 +292,10 @@ class track_var
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ return;
+
+- value[regno] = gen_rtx_raw_CONST_INT (mode, 0x100000000000000LL | ((long long int) (regno) << 32) | index);
+- mask[regno] = 1<<FIRST_PSEUDO_REGISTER;
++ if (mode == SFmode && regno < 16)
++ mode = SImode;
++ value[regno] = gen_rtx_raw_CONST_INT(mode, 0x100000000000000LL | ((long long int ) (regno) << 32) | index);
++ mask[regno] = 1 << FIRST_PSEUDO_REGISTER;
+ }
+
+ void
+@@ -299,7 +303,7 @@ class track_var
+ {
+ for (int i = 2; i < FIRST_PSEUDO_REGISTER; ++i)
+ {
+- if (mask[i] && mask[i] < 1<<FIRST_PSEUDO_REGISTER)
++ if (mask[i] && mask[i] < 1 << FIRST_PSEUDO_REGISTER)
+ {
+ value[i] = 0;
+ mask[i] = 0;
+@@ -3927,7 +3931,7 @@ track_regs ()
+ continue;
+
+ int dregno = ii.get_dst_regno ();
+- track->clear (ii.get_mode(), dregno, index);
++ track->clear (ii.get_mode (), dregno, index);
+
+ unsigned def = ii.get_def () & 0xffffff;
+ track->clear_for_mask (def, index);
+@@ -4628,9 +4632,9 @@ namespace
+ bool ispicref = false;
+ // fix add PLUS/MINUS into the unspec offset
+ if (GET_CODE(*src) == PLUS || GET_CODE(*src) == MINUS)
+- ispicref = amiga_is_const_pic_ref(XEXP(*src, 0));
++ ispicref = amiga_is_const_pic_ref (XEXP(*src, 0));
+ else
+- ispicref = amiga_is_const_pic_ref(*src);
++ ispicref = amiga_is_const_pic_ref (*src);
+
+ if (ispicref)
+ {
+
+From b9eb7c80c772836b151ec2ae333c15d1ea744e18 Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Mon, 11 Dec 2017 12:06:10 +0100
+Subject: [PATCH 278/303] bump version DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index e90d802ff727..a8c69c9addb5 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20171203-234342
++20171211-120610
+
+From 7b5b41278acb1bf3ca163b4adab55c08994cea6d Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Mon, 11 Dec 2017 23:26:17 +0100
+Subject: [PATCH 279/303] do not use hoist with -Os use also pre
+
+---
+ gcc/gcse.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/gcc/gcse.c b/gcc/gcse.c
+index 5b2c96ecb5a6..f74e733f9337 100644
+--- gcc/gcse.c
++++ gcc/gcse.c
+@@ -4075,7 +4075,9 @@ pass_rtl_pre::gate (function *fun)
+ {
+ return optimize > 0 && flag_gcse
+ && !fun->calls_setjmp
++#ifndef TARGET_AMIGA
+ && optimize_function_for_speed_p (fun)
++#endif
+ && dbg_cnt (pre);
+ }
+
+@@ -4118,6 +4120,9 @@ class pass_rtl_hoist : public rtl_opt_pass
+ bool
+ pass_rtl_hoist::gate (function *)
+ {
++#ifdef TARGET_AMIGA
++ return false;
++#else
+ return optimize > 0 && flag_gcse
+ && !cfun->calls_setjmp
+ /* It does not make sense to run code hoisting unless we are optimizing
+@@ -4125,6 +4130,7 @@ pass_rtl_hoist::gate (function *)
+ bigger if we did PRE (when optimizing for space, we don't run PRE). */
+ && optimize_function_for_size_p (cfun)
+ && dbg_cnt (hoist);
++#endif
+ }
+
+ } // anon namespace
+
+From 96f443e1846b944a8a665d0408574691dcca3259 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 12 Dec 2017 18:25:13 +0100
+Subject: [PATCH 280/303] fix g++ executable dependency to install-cpp
+
+---
+ gcc/Makefile.in | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/Makefile.in b/gcc/Makefile.in
+index 2871c5794c4b..4aedf54bab12 100644
+--- gcc/Makefile.in
++++ gcc/Makefile.in
+@@ -3271,7 +3271,7 @@ endif
+ install-strip: install
+
+ # Handle cpp installation.
+-install-cpp: installdirs cpp$(exeext)
++install-cpp: installdirs cpp$(exeext) all.cross
+ -if test "$(enable_as_accelerator)" != "yes" ; then \
+ rm -f $(DESTDIR)$(bindir)/$(CPP_INSTALL_NAME)$(exeext); \
+ $(INSTALL_PROGRAM) -m 755 cpp$(exeext) $(DESTDIR)$(bindir)/$(CPP_INSTALL_NAME)$(exeext); \
+
+From d42099d1dc94abdec1291e32149c77e2ec1533d0 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 12 Dec 2017 18:25:57 +0100
+Subject: [PATCH 281/303] fix handling SIGN_EXTEND in opt_auto_inc
+
+---
+ gcc/bbb-opts.c | 2 +-
+ gcc/config/m68k/amigaos.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index f54fb54d4405..585e719c2d5c 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -1021,7 +1021,7 @@ insn_info::make_post_inc (int regno)
+
+ if (src_op && get_src_mem_regno () == regno)
+ {
+- if (src_op == NEG || src_op == NOT)
++ if (src_op == NEG || src_op == NOT || src_op == SIGN_EXTEND)
+ mem = XEXP(mem, 0);
+ else
+ mem = XEXP(mem, 1);
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index 1fe7d09b0142..60779c6579fc 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -939,7 +939,7 @@ amigaos_legitimate_src (rtx src)
+ if (GET_CODE(op) == MINUS || GET_CODE(op) == PLUS)
+ {
+ rtx x = XEXP(op, 0);
+- if (GET_CODE(x) == NOT || GET_CODE(x) == NEG)
++ if (GET_CODE(x) == NOT || GET_CODE(x) == NEG || GET_CODE(x) == SIGN_EXTEND)
+ {
+ rtx reg = XEXP(x, 0);
+ if (!REG_P(reg))
+
+From c7ef0dc43dc68aebf4d27df6749c3a09b054d6e0 Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Tue, 12 Dec 2017 19:07:22 +0100
+Subject: [PATCH 282/303] bump version DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index a8c69c9addb5..8f1a6c8420aa 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20171211-120610
++20171212-190722
+
+From 8b8789f06d99d60e60727b5a51690538d6dc403d Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 19 Dec 2017 16:51:50 +0100
+Subject: [PATCH 283/303] do not deduplicate jump tables with 68000 since the 8
+ bits pcrel offset might be to small
+
+---
+ gcc/cfgcleanup.c | 14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c
+index 6e92d4cdde22..fddd9dd25458 100644
+--- gcc/cfgcleanup.c
++++ gcc/cfgcleanup.c
+@@ -2001,6 +2001,14 @@ try_crossjump_to_edge (int mode, edge e1, edge e2,
+ {
+ rtx_insn *insn;
+
++#ifdef TARGET_AMIGA
++ /*
++ * we need replicated labels, if the labels are too far away,
++ * since on 68000 there are only 8 bits for the offset.
++ */
++ if (TARGET_68020 || TARGET_68040)
++#endif
++
+ /* Replace references to LABEL1 with LABEL2. */
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ {
+@@ -2016,8 +2024,12 @@ try_crossjump_to_edge (int mode, edge e1, edge e2,
+ /* Avoid splitting if possible. We must always split when SRC2 has
+ EH predecessor edges, or we may end up with basic blocks with both
+ normal and EH predecessor edges. */
+- if (newpos2 == BB_HEAD (src2)
++ if ((newpos2 == BB_HEAD (src2)
+ && !(EDGE_PRED (src2, 0)->flags & EDGE_EH))
++#ifdef TARGET_AMIGA
++ || (!TARGET_68020 && !TARGET_68040)
++#endif
++ )
+ redirect_to = src2;
+ else
+ {
+
+From 8a91b7265bab01a1011c8f153323732d9eee48cf Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Tue, 19 Dec 2017 18:34:20 +0100
+Subject: [PATCH 284/303] fix last patch
+
+---
+ gcc/cfgcleanup.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c
+index fddd9dd25458..378b1fc595bb 100644
+--- gcc/cfgcleanup.c
++++ gcc/cfgcleanup.c
+@@ -2006,7 +2006,8 @@ try_crossjump_to_edge (int mode, edge e1, edge e2,
+ * we need replicated labels, if the labels are too far away,
+ * since on 68000 there are only 8 bits for the offset.
+ */
+- if (TARGET_68020 || TARGET_68040)
++ if (!TARGET_68020 && !TARGET_68040)
++ return false;
+ #endif
+
+ /* Replace references to LABEL1 with LABEL2. */
+@@ -2026,9 +2027,6 @@ try_crossjump_to_edge (int mode, edge e1, edge e2,
+ normal and EH predecessor edges. */
+ if ((newpos2 == BB_HEAD (src2)
+ && !(EDGE_PRED (src2, 0)->flags & EDGE_EH))
+-#ifdef TARGET_AMIGA
+- || (!TARGET_68020 && !TARGET_68040)
+-#endif
+ )
+ redirect_to = src2;
+ else
+
+From 490ff33de1b66b808166de62b512e321fb412918 Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Tue, 19 Dec 2017 19:03:07 +0100
+Subject: [PATCH 285/303] bump version DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 8f1a6c8420aa..8426e3db7f19 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20171212-190722
++20171219-190306
+
+From 775d5c86463a8acca838702ce6e5e7d97a5ca102 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 21 Dec 2017 19:19:07 +0100
+Subject: [PATCH 286/303] support section switching and provide the current
+ var_decl
+
+---
+ gcc/varasm.c | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/varasm.c b/gcc/varasm.c
+index b65f29c13a46..8ead5ec3fcbb 100644
+--- gcc/varasm.c
++++ gcc/varasm.c
+@@ -252,7 +252,6 @@ get_unnamed_section (unsigned int flags, void (*callback) (const void *),
+ sect->unnamed.callback = callback;
+ sect->unnamed.data = data;
+ sect->unnamed.next = unnamed_sections;
+-
+ unnamed_sections = sect;
+ return sect;
+ }
+@@ -2228,11 +2227,17 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED,
+ else
+ {
+ /* Special-case handling of vtv comdat sections. */
+- if (sect->named.name
++ if ((sect->common.flags & SECTION_STYLE_MASK) == SECTION_NAMED && sect->named.name
+ && (strcmp (sect->named.name, ".vtable_map_vars") == 0))
+ handle_vtv_comdat_section (sect, decl);
+ else
+- switch_to_section (sect);
++ {
++#ifdef TARGET_AMIGA
++ if ((sect->common.flags & SECTION_STYLE_MASK) == SECTION_NAMED)
++ sect->named.decl = decl;
++#endif
++ switch_to_section (sect);
++ }
+ if (align > BITS_PER_UNIT)
+ ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
+ assemble_variable_contents (decl, name, dont_output_data);
+@@ -4962,7 +4967,7 @@ output_constructor_regular_field (oc_local_state *local)
+ if each element has the proper size. */
+ if (local->field != NULL_TREE || local->index != NULL_TREE)
+ {
+- if (fieldpos > local->total_bytes)
++ if (fieldpos >= local->total_bytes)
+ {
+ assemble_zeros (fieldpos - local->total_bytes);
+ local->total_bytes = fieldpos;
+
+From 21ecb9edff4c412a373ff9c1d3cb0ddc1d2ffdb9 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 21 Dec 2017 19:23:02 +0100
+Subject: [PATCH 287/303] added support for __chip, __fast and __far attributes
+
+---
+ gcc/config/m68k/amigaos.c | 207 +++++++++++-------------------------------
+ gcc/config/m68k/amigaos.h | 5 +-
+ gcc/config/m68k/m68k.c | 7 +-
+ gcc/config/m68k/m68kamigaos.h | 14 ++-
+ 4 files changed, 72 insertions(+), 161 deletions(-)
+
+diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c
+index 60779c6579fc..28d20a980978 100644
+--- gcc/config/m68k/amigaos.c
++++ gcc/config/m68k/amigaos.c
+@@ -52,152 +52,6 @@
+ //int amiga_declare_object;
+
+ #if 0
+-static int amigaos_put_in_text (tree);
+-static rtx gen_stack_management_call (rtx, rtx, const char *);
+-
+-/* Baserel support. */
+-
+-/* Does operand (which is a symbolic_operand) live in text space? If
+- so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true.
+-
+- This function is used in base relative code generation. */
+-
+-int
+-read_only_operand (rtx operand)
+- {
+- if (GET_CODE (operand) == CONST)
+- operand = XEXP (XEXP (operand, 0), 0);
+- if (GET_CODE (operand) == SYMBOL_REF)
+- return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand);
+- return 1;
+- }
+-
+-/* Choose the section to use for DECL. RELOC is true if its value contains
+- any relocatable expression. */
+-
+-void
+-amigaos_select_section (tree decl ATTRIBUTE_UNUSED, int reloc ATTRIBUTE_UNUSED,
+- unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
+- {
+- // if (TREE_CODE (decl) == STRING_CST)
+-// {
+-//// flag_writable_strings /data_section not in gcc4,
+-////make life easy and put to same section
+-//// if (! flag_writable_strings)
+-//// readonly_data_section ();
+-//// else
+-// //data_section ();
+-// }
+-// else if (TREE_CODE (decl) == VAR_DECL)
+-// {
+-// if (TREE_READONLY (decl)
+-// && ! TREE_THIS_VOLATILE (decl)
+-// && DECL_INITIAL (decl)
+-// && (DECL_INITIAL (decl) == error_mark_node
+-// || TREE_CONSTANT (DECL_INITIAL (decl)))
+-// && (!flag_pic || (flag_pic<3 && !reloc)
+-// || SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0))))
+-// readonly_data_section ();
+-// else
+-// data_section ();
+-// }
+-// else if ((!flag_pic || (flag_pic<3 && !reloc)) && DECL_P(decl)
+-// && SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)))
+-// readonly_data_section ();
+-// else
+- //data_section ();
+- }
+-
+-/* This function is used while generating a base relative code.
+- It returns 1 if a decl is not relocatable, i. e., if it can be put
+- in the text section.
+- Currently, it's very primitive: it just checks if the object size
+- is less than 4 bytes (i. e., if it can hold a pointer). It also
+- supports arrays and floating point types. */
+-
+-static int
+-amigaos_put_in_text (tree decl)
+- {
+- tree type = TREE_TYPE (decl);
+- if (TREE_CODE (type) == ARRAY_TYPE)
+- type = TREE_TYPE (type);
+- return (TREE_INT_CST_ELT(TYPE_SIZE (type), 1) == 0
+- && TREE_INT_CST_LOW (TYPE_SIZE (type)) < 32)
+- || FLOAT_TYPE_P (type);
+- }
+-
+-/* Record properties of a DECL into the associated SYMBOL_REF. */
+-
+-void
+-amigaos_encode_section_info (tree decl, rtx rtl, int first)
+- {
+- default_encode_section_info (decl, rtl, first);
+-
+- SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
+- if (TREE_CODE (decl) == FUNCTION_DECL) // huh seem do same. not in gcc4 flag_writable_strings
+- SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
+- else
+- {
+- if ((MEM_READONLY_P (rtl) && !MEM_VOLATILE_P (rtl)
+- && (flag_pic<3 || (TREE_CODE (decl) == STRING_CST
+- )
+- || amigaos_put_in_text (decl)))
+- || (TREE_CODE (decl) == VAR_DECL
+- && DECL_SECTION_NAME (decl) != NULL))
+- SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
+- }
+- }
+-
+-
+-/* Attributes support. */
+-
+-#define AMIGA_CHIP_SECTION_NAME ".datachip"
+-
+-/* Handle a "chip" attribute;
+- arguments as in struct attribute_spec.handler. */
+-
+-tree
+-amigaos_handle_decl_attribute (tree *node, tree name,
+- tree args ATTRIBUTE_UNUSED,
+- int flags ATTRIBUTE_UNUSED,
+- bool *no_add_attrs)
+- {
+- if (TREE_CODE (*node) == VAR_DECL)
+- {
+- if (is_attribute_p ("chip", name))
+-#ifdef TARGET_ASM_NAMED_SECTION
+- {
+- if (! TREE_STATIC (*node) && ! DECL_EXTERNAL (*node))
+- error ("`chip' attribute cannot be specified for local variables");
+- else
+- {
+- /* The decl may have already been given a section attribute from
+- a previous declaration. Ensure they match. */
+- if (DECL_SECTION_NAME (*node) == NULL_TREE)
+- DECL_SECTION_NAME (*node) =
+- build_string (strlen (AMIGA_CHIP_SECTION_NAME) + 1,
+- AMIGA_CHIP_SECTION_NAME);
+- else if (strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (*node)),
+- AMIGA_CHIP_SECTION_NAME) != 0)
+- {
+- error_with_decl (*node,
+- "`chip' for `%s' conflicts with previous declaration");
+- }
+- }
+- }
+-#else
+- error ("`chip' attribute is not supported for this target");
+-#endif
+- }
+- else
+- {
+- warning (OPT_Wattributes, "`%s' attribute only applies to variables",
+- IDENTIFIER_POINTER (name));
+- *no_add_attrs = true;
+- }
+-
+- return NULL_TREE;
+- }
+
+ //----- from 68k.c start
+
+@@ -607,6 +461,31 @@ amigaos_comp_type_attributes (const_tree type1, const_tree type2)
+ return 0;
+
+ }
++ else
++ {
++ tree attrs1 = TYPE_ATTRIBUTES(type1);
++
++ tree chip1 = lookup_attribute("chip", attrs1);
++ tree fast1 = lookup_attribute("fast", attrs1);
++ tree far1 = lookup_attribute("far", attrs1);
++
++ tree attrs2 = TYPE_ATTRIBUTES(type2);
++
++ tree chip2 = lookup_attribute("chip", attrs2);
++ tree fast2 = lookup_attribute("fast", attrs2);
++ tree far2 = lookup_attribute("far", attrs2);
++
++ if (chip1)
++ return chip2 && !fast2 && !far2;
++
++ if (fast1)
++ return !chip2 && fast2 && !far2;
++
++ if (far1)
++ return !chip2 && !fast2 && far2;
++
++ return !chip2 && !fast2 && !far2;
++ }
+ return 1;
+ }
+ /* end-GG-local */
+@@ -689,7 +568,7 @@ amigaos_handle_type_attribute (tree *node, tree name, tree args, int flags ATTRI
+ }
+ else
+ {
+- if (is_attribute_p ("chip", name))
++ if (is_attribute_p ("chip", name) || is_attribute_p ("fast", name) || is_attribute_p ("far", name))
+ {
+ // OK
+ }
+@@ -707,6 +586,8 @@ amigaos_handle_type_attribute (tree *node, tree name, tree args, int flags ATTRI
+ }
+
+ #define AMIGA_CHIP_SECTION_NAME ".datachip"
++#define AMIGA_FAST_SECTION_NAME ".datafast"
++#define AMIGA_FAR_SECTION_NAME ".datafar"
+
+ void
+ amiga_insert_attribute (tree decl, tree * attr)
+@@ -716,28 +597,37 @@ amiga_insert_attribute (tree decl, tree * attr)
+
+ tree name = TREE_PURPOSE(*attr);
+
+- if (is_attribute_p("chip", name))
++ if (is_attribute_p("chip", name) || is_attribute_p("far", name) || is_attribute_p("fast", name))
+ {
+ if (!TREE_TYPE(decl) == VAR_DECL)
+ {
+- error ("`chip' attribute can only be specified for variables");
++ error ("`%s' attribute can only be specified for variables", IDENTIFIER_POINTER(name));
+ return;
+ }
+
+ if (! TREE_STATIC (decl) && ! DECL_EXTERNAL (decl))
+ {
+- error ("`chip' attribute cannot be specified for local variables");
++ error ("`%s' attribute cannot be specified for local variables", IDENTIFIER_POINTER(name));
+ return;
+ }
++
++ char const * section_name;
++ if (is_attribute_p("chip", name))
++ section_name = AMIGA_CHIP_SECTION_NAME;
++ else if (is_attribute_p("fast", name))
++ section_name = AMIGA_FAST_SECTION_NAME;
++ else if (is_attribute_p("far", name))
++ section_name = AMIGA_FAR_SECTION_NAME;
++
++
+ /* The decl may have already been given a section attribute from
+ a previous declaration. Ensure they match. */
+ if (DECL_SECTION_NAME (decl) == NULL)
+- warning (OPT_Wattributes, "`%s' attribute is not yet supported", IDENTIFIER_POINTER(name));
+-// set_decl_section_name(decl, AMIGA_CHIP_SECTION_NAME);
+- else if (strcmp (DECL_SECTION_NAME (decl), AMIGA_CHIP_SECTION_NAME) )
++ set_decl_section_name(decl, section_name);
++ else if (strcmp (DECL_SECTION_NAME (decl), section_name) )
+ {
+ error_at (DECL_SOURCE_LOCATION(decl),
+- "`chip' attribute conflicts with previous declaration");
++ "`%s' attribute conflicts with previous declaration", IDENTIFIER_POINTER(name));
+ }
+ }
+ else
+@@ -763,11 +653,16 @@ amigaos_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno, int *tota
+ /* Output assembly to switch to section NAME with attribute FLAGS. */
+ #ifndef TARGET_AMIGAOS_VASM
+ extern void
+-amiga_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_UNUSED)
++amiga_named_section (const char *name, unsigned int flags, tree decl )
+ {
++ // only one code section - TODO: with amiga hunk this is no longer mandatory.
+ if (0 == strncmp (".text", name, 5))
+ name = ".text";
+- fprintf (asm_out_file, "\t%s\n", name);
++
++ if (0 == strncmp(".data", name, 5) && (!DECL_INITIAL (decl) || initializer_zerop (DECL_INITIAL (decl))))
++ fprintf (asm_out_file, "\t.bss%s\n", name + 5);
++ else
++ fprintf (asm_out_file, "\t%s\n", name);
+ }
+ #else
+ extern void
+diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h
+index 723c36969ad1..1b60ed633a3a 100644
+--- gcc/config/m68k/amigaos.h
++++ gcc/config/m68k/amigaos.h
+@@ -118,7 +118,8 @@ Boston, MA 02111-1307, USA. */
+ N_("Do not restore a4 in all functions") }
+
+
+-/* Support sections in chip memory, currently '.datachip' only. */
++/* Support sections in chip, fast memory, currently '.datachip', '.datafast'
++ * and '.datafar' to abs addressing with baserel. */
+ extern void
+ amiga_named_section (const char *name, unsigned int flags, tree decl);
+
+@@ -445,6 +446,8 @@ while (0)
+ #define SUBTARGET_ATTRIBUTES \
+ { "asmregs", 0, 0, false, false, false, 0, true }, \
+ { "chip", 0, 0, false, true, false, amigaos_handle_type_attribute, false }, \
++ { "fast", 0, 0, false, true, false, amigaos_handle_type_attribute, false }, \
++ { "far", 0, 0, false, true, false, amigaos_handle_type_attribute, false }, \
+ { "saveds", 0, 0, false, true, true, amigaos_handle_type_attribute, false }, \
+ { "regparm", 1, 1, false, true, true, amigaos_handle_type_attribute,\
+ true }, \
+diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
+index 0a67f320bc1d..85ed75e9fce7 100644
+--- gcc/config/m68k/m68k.c
++++ gcc/config/m68k/m68k.c
+@@ -2534,8 +2534,13 @@ legitimize_pic_address (rtx orig, machine_mode mode ATTRIBUTE_UNUSED,
+ /* SBF: Does the symbol use common or bss and qualifies for pic_reg?
+ * Do not ref to .text via pic_reg!
+ */
+- if (GET_CODE (orig) == SYMBOL_REF && !SYMBOL_REF_FUNCTION_P(orig) && decl && (DECL_COMMON (decl) || bss_initializer_p (decl)))
++ char const * section = decl ? DECL_SECTION_NAME(decl) : 0;
++ if (GET_CODE (orig) == SYMBOL_REF && !orig->frame_related && !SYMBOL_REF_FUNCTION_P(orig) && decl
++ && !decl->common.typed.base.readonly_flag
++ && !decl->decl_with_vis.in_text_section && !section)
+ {
++// fprintf(stderr, "(a4) for: %s\n", decl->decl_minimal.name->identifier.id.str);
++
+ /* SBF: unfortunately using the wrapped symbol without MEM does not work.
+ * The pic_ref reference gets decomposed and leads to no working code.
+ */
+diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h
+index 43ffcd0add39..83d1acb9d1e3 100644
+--- gcc/config/m68k/m68kamigaos.h
++++ gcc/config/m68k/m68kamigaos.h
+@@ -227,13 +227,19 @@ amiga_declare_object = 0
+ /* end of stuff from m68kv4.h */
+
+ #ifndef TARGET_AMIGAOS_VASM
+-#ifndef BSS_SECTION_ASM_OP
++#undef BSS_SECTION_ASM_OP
+ #define BSS_SECTION_ASM_OP "\t.bss"
+-#endif
+ #else
+ #define BSS_SECTION_ASM_OP "\tsection\tbss"
+ #endif
+
++#ifndef TARGET_AMIGAOS_VASM
++#undef DATA_SECTION_ASM_OP
++#define DATA_SECTION_ASM_OP "\t.data"
++#else
++#define DATA_SECTION_ASM_OP "\tsection\tdata"
++#endif
++
+ #ifndef ASM_OUTPUT_ALIGNED_BSS
+ #define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
+ asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
+@@ -252,6 +258,8 @@ amiga_declare_object = 0
+ do \
+ { \
+ builtin_define ("__chip=__attribute__((__chip__))"); \
++ builtin_define ("__fast=__attribute__((__fast__))"); \
++ builtin_define ("__far=__attribute__((__far__))"); \
+ builtin_define ("__saveds=__attribute__((__saveds__))"); \
+ builtin_define ("__interrupt=__attribute__((__interrupt__))"); \
+ builtin_define ("__stackext=__attribute__((__stackext__))"); \
+@@ -360,7 +368,7 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \
+ #undef ASM_SPEC
+ #ifndef TARGET_AMIGAOS_VASM
+ #define ASM_SPEC \
+- "%(asm_cpu) %(asm_cpu_default) %{msmall-code:-sc}"
++ "%(asm_cpu) %(asm_cpu_default) %{msmall-code:-sc} %{!msmall-code:-S}"
+ #else
+ #define ASM_SPEC \
+ "-gas -esc -ldots -Fhunk -quiet %(asm_cpu) %(asm_cpu_default) %{msmall-code:-sc}"
+
+From c28c2cf8d727bb5bd0a1e98e9c9ca5c56635420f Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Thu, 21 Dec 2017 19:50:03 +0100
+Subject: [PATCH 288/303] bump version DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 8426e3db7f19..2d76043c1dd3 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20171219-190306
++20171221-195003
+
+From 40681c48c17fade42d96ffc1f405c2cc25bd7527 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sat, 23 Dec 2017 11:07:32 +0100
+Subject: [PATCH 289/303] access DECL stuff only if it is a SYMBOL_REF
+
+---
+ gcc/config/m68k/m68k.c | 7 +++----
+ gcc/config/m68k/m68k.h | 4 ++--
+ 2 files changed, 5 insertions(+), 6 deletions(-)
+
+diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
+index 85ed75e9fce7..d6accd3bfd8d 100644
+--- gcc/config/m68k/m68k.c
++++ gcc/config/m68k/m68k.c
+@@ -2529,17 +2529,16 @@ legitimize_pic_address (rtx orig, machine_mode mode ATTRIBUTE_UNUSED,
+ #ifdef TARGET_AMIGA
+ else
+ {
+- tree decl = SYMBOL_REF_DECL (orig);
+
+ /* SBF: Does the symbol use common or bss and qualifies for pic_reg?
+ * Do not ref to .text via pic_reg!
+ */
+- char const * section = decl ? DECL_SECTION_NAME(decl) : 0;
+- if (GET_CODE (orig) == SYMBOL_REF && !orig->frame_related && !SYMBOL_REF_FUNCTION_P(orig) && decl
++ tree decl;
++ if (GET_CODE (orig) == SYMBOL_REF && !orig->frame_related && !SYMBOL_REF_FUNCTION_P(orig)
++ && (decl = SYMBOL_REF_DECL (orig)) && !(DECL_SECTION_NAME(decl))
+ && !decl->common.typed.base.readonly_flag
+ && !decl->decl_with_vis.in_text_section && !section)
+ {
+-// fprintf(stderr, "(a4) for: %s\n", decl->decl_minimal.name->identifier.id.str);
+
+ /* SBF: unfortunately using the wrapped symbol without MEM does not work.
+ * The pic_ref reference gets decomposed and leads to no working code.
+diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h
+index 200f07ef63a4..6cdc635d4df3 100644
+--- gcc/config/m68k/m68k.h
++++ gcc/config/m68k/m68k.h
+@@ -620,11 +620,11 @@ __transfer_from_trampoline () \
+
+ #define REGNO_OK_FOR_INDEX_P(REGNO) \
+ (INT_REGNO_P (REGNO) \
+- || INT_REGNO_P (reg_renumber[REGNO]))
++ || (reg_renumber && INT_REGNO_P (reg_renumber[REGNO])))
+
+ #define REGNO_OK_FOR_BASE_P(REGNO) \
+ (ADDRESS_REGNO_P (REGNO) \
+- || ADDRESS_REGNO_P (reg_renumber[REGNO]))
++ || (reg_renumber && ADDRESS_REGNO_P (reg_renumber[REGNO])))
+
+ #define REGNO_OK_FOR_INDEX_NONSTRICT_P(REGNO) \
+ (INT_REGNO_P (REGNO) \
+
+From 8b9a647f47952ea1411a54e51f5406fb79a3e30d Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sat, 23 Dec 2017 11:08:23 +0100
+Subject: [PATCH 290/303] more compatible way to apply register renaming
+
+---
+ gcc/bbb-opts.c | 64 ++++++++++++++++++----------------------------------------
+ 1 file changed, 20 insertions(+), 44 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 585e719c2d5c..432c9bb4bbd3 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -1452,11 +1452,11 @@ copy_reg (rtx reg, int newregno)
+ }
+
+ /* Rename the register plus track all locs to undo these changes. */
+-static void
+-temp_reg_rename (std::vector<std::pair<rtx *, rtx> > & loc, rtx x, unsigned oldregno, unsigned newregno)
++static rtx
++find_reg_by_no (rtx x, unsigned oldregno)
+ {
+ if (!x)
+- return;
++ return 0;
+
+ RTX_CODE code = GET_CODE(x);
+
+@@ -1469,27 +1469,25 @@ temp_reg_rename (std::vector<std::pair<rtx *, rtx> > & loc, rtx x, unsigned oldr
+ if (REG_P(y))
+ {
+ if (REGNO(y) == oldregno)
+- {
+- rtx z = copy_reg (y, newregno);
+- loc.push_back (std::make_pair (&XEXP(x, i), y));
+- XEXP(x, i) = z;
+- }
++ return y;
+ }
+ else
+- temp_reg_rename (loc, y, oldregno, newregno);
++ {
++ rtx r = find_reg_by_no (y, oldregno);
++ if (r)
++ return r;
++ }
+ }
+ else if (fmt[i] == 'E')
+ for (int j = XVECLEN (x, i) - 1; j >= 0; j--)
+ {
+ rtx z = XVECEXP(x, i, j);
+- if (GET_CODE(z) == CLOBBER)
+- {
+- /* workaround for shared clobbers. */
+- XVECEXP(x, i, j) = z = gen_rtx_CLOBBER(GET_MODE(z), XEXP(z, 0));
+- }
+- temp_reg_rename (loc, z, oldregno, newregno);
++ rtx r = find_reg_by_no(z, oldregno);
++ if (r)
++ return r;
+ }
+ }
++ return 0;
+ }
+
+ /*
+@@ -2454,45 +2452,27 @@ opt_reg_rename (void)
+
+ /* check the renamed insns. */
+ std::vector<unsigned> positions;
+- std::vector<std::pair<rtx *, rtx> > locs;
+- std::vector<std::pair<rtx *, rtx> > patch;
+- bool ok = true;
+-
+- for (std::set<unsigned>::iterator i = found.begin (); ok && i != found.end (); ++i)
++ for (std::set<unsigned>::iterator i = found.begin (); i != found.end (); ++i)
+ {
+ insn_info & rr = infos[*i];
+ rtx_insn * insn = rr.get_insn ();
+
+- /* temp rename. */
+- temp_reg_rename (locs, PATTERN (insn), oldregno, newregno);
+- if (!locs.empty ())
++ /* get rename locations. */
++ rtx from = find_reg_by_no(PATTERN (insn), oldregno);
++ if (from)
+ {
+- if (insn_invalid_p (insn, 1))
+- ok = false;
+-
+- /* undo temp change but keep loc and new register. */
+- for (std::vector<std::pair<rtx *, rtx> >::iterator j = locs.begin (); j != locs.end (); ++j)
+- {
+- patch.push_back (std::make_pair (j->first, *j->first));
+- *j->first = j->second;
+- }
++ rtx to = gen_raw_REG(GET_MODE(from), newregno);
++ validate_replace_rtx_group(from, to, insn);
+
+ positions.push_back (*i);
+- locs.clear ();
+ }
+ }
+
+- if (!ok)
+- {
+- cancel_changes (0);
+- continue;
+- }
+-
+ if (!apply_change_group ())
+ continue;
+
+ log ("(r) opt_reg_rename %s -> %s (%d locs, start at %d)\n", reg_names[oldregno], reg_names[newregno],
+- patch.size (), index);
++ positions.size (), index);
+
+ if (be_verbose)
+ {
+@@ -2502,10 +2482,6 @@ opt_reg_rename (void)
+ fflush (stdout);
+ }
+
+- /* apply all changes. */
+- for (std::vector<std::pair<rtx *, rtx> >::iterator j = patch.begin (); j != patch.end (); ++j)
+- *j->first = j->second;
+-
+ return 1;
+ }
+ }
+
+From 3b4383bb016fb3c48ee7fbc30a9737370dc7d56b Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sat, 23 Dec 2017 11:53:34 +0100
+Subject: [PATCH 291/303] fix compile error - uups
+
+---
+ gcc/config/m68k/m68k.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
+index d6accd3bfd8d..29e2e45df844 100644
+--- gcc/config/m68k/m68k.c
++++ gcc/config/m68k/m68k.c
+@@ -2537,7 +2537,7 @@ legitimize_pic_address (rtx orig, machine_mode mode ATTRIBUTE_UNUSED,
+ if (GET_CODE (orig) == SYMBOL_REF && !orig->frame_related && !SYMBOL_REF_FUNCTION_P(orig)
+ && (decl = SYMBOL_REF_DECL (orig)) && !(DECL_SECTION_NAME(decl))
+ && !decl->common.typed.base.readonly_flag
+- && !decl->decl_with_vis.in_text_section && !section)
++ && !decl->decl_with_vis.in_text_section)
+ {
+
+ /* SBF: unfortunately using the wrapped symbol without MEM does not work.
+
+From 5eb6023e66b9bdf3125e5381d11ac9992835f943 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Sat, 23 Dec 2017 11:54:08 +0100
+Subject: [PATCH 292/303] fix inlined functions - removed extern
+
+---
+ gcc/config/m68k/math-68881.h | 62 ++++++++++++++++++++++----------------------
+ 1 file changed, 31 insertions(+), 31 deletions(-)
+
+diff --git a/gcc/config/m68k/math-68881.h b/gcc/config/m68k/math-68881.h
+index 6d9f8b2d4a1f..20a5037cc525 100644
+--- gcc/config/m68k/math-68881.h
++++ gcc/config/m68k/math-68881.h
+@@ -37,7 +37,7 @@
+ September 1993, Use #undef before HUGE_VAL instead of #ifdef/#endif. */
+
+ /* Changed by Ian Lance Taylor:
+- September 1994, use extern inline instead of static inline. */
++ September 1994, use inline instead of static inline. */
+
+ #ifndef __math_68881
+ #define __math_68881
+@@ -64,7 +64,7 @@
+ })
+ #endif
+
+-__inline extern double
++__inline double
+ sin (double x)
+ {
+ double value;
+@@ -75,7 +75,7 @@ sin (double x)
+ return value;
+ }
+
+-__inline extern double
++__inline double
+ cos (double x)
+ {
+ double value;
+@@ -86,7 +86,7 @@ cos (double x)
+ return value;
+ }
+
+-__inline extern double
++__inline double
+ tan (double x)
+ {
+ double value;
+@@ -97,7 +97,7 @@ tan (double x)
+ return value;
+ }
+
+-__inline extern double
++__inline double
+ asin (double x)
+ {
+ double value;
+@@ -108,7 +108,7 @@ asin (double x)
+ return value;
+ }
+
+-__inline extern double
++__inline double
+ acos (double x)
+ {
+ double value;
+@@ -119,7 +119,7 @@ acos (double x)
+ return value;
+ }
+
+-__inline extern double
++__inline double
+ atan (double x)
+ {
+ double value;
+@@ -130,7 +130,7 @@ atan (double x)
+ return value;
+ }
+
+-__inline extern double
++__inline double
+ atan2 (double y, double x)
+ {
+ double pi, pi_over_2;
+@@ -187,7 +187,7 @@ atan2 (double y, double x)
+ }
+ }
+
+-__inline extern double
++__inline double
+ sinh (double x)
+ {
+ double value;
+@@ -198,7 +198,7 @@ sinh (double x)
+ return value;
+ }
+
+-__inline extern double
++__inline double
+ cosh (double x)
+ {
+ double value;
+@@ -209,7 +209,7 @@ cosh (double x)
+ return value;
+ }
+
+-__inline extern double
++__inline double
+ tanh (double x)
+ {
+ double value;
+@@ -220,7 +220,7 @@ tanh (double x)
+ return value;
+ }
+
+-__inline extern double
++__inline double
+ atanh (double x)
+ {
+ double value;
+@@ -231,7 +231,7 @@ atanh (double x)
+ return value;
+ }
+
+-__inline extern double
++__inline double
+ exp (double x)
+ {
+ double value;
+@@ -242,7 +242,7 @@ exp (double x)
+ return value;
+ }
+
+-__inline extern double
++__inline double
+ expm1 (double x)
+ {
+ double value;
+@@ -253,7 +253,7 @@ expm1 (double x)
+ return value;
+ }
+
+-__inline extern double
++__inline double
+ log (double x)
+ {
+ double value;
+@@ -264,7 +264,7 @@ log (double x)
+ return value;
+ }
+
+-__inline extern double
++__inline double
+ log1p (double x)
+ {
+ double value;
+@@ -275,7 +275,7 @@ log1p (double x)
+ return value;
+ }
+
+-__inline extern double
++__inline double
+ log10 (double x)
+ {
+ double value;
+@@ -286,7 +286,7 @@ log10 (double x)
+ return value;
+ }
+
+-__inline extern double
++__inline double
+ sqrt (double x)
+ {
+ double value;
+@@ -297,13 +297,13 @@ sqrt (double x)
+ return value;
+ }
+
+-__inline extern double
++__inline double
+ hypot (double x, double y)
+ {
+ return sqrt (x*x + y*y);
+ }
+
+-__inline extern double
++__inline double
+ pow (double x, double y)
+ {
+ if (x > 0)
+@@ -352,7 +352,7 @@ pow (double x, double y)
+ }
+ }
+
+-__inline extern double
++__inline double
+ fabs (double x)
+ {
+ double value;
+@@ -363,7 +363,7 @@ fabs (double x)
+ return value;
+ }
+
+-__inline extern double
++__inline double
+ ceil (double x)
+ {
+ int rounding_mode, round_up;
+@@ -385,7 +385,7 @@ ceil (double x)
+ return value;
+ }
+
+-__inline extern double
++__inline double
+ floor (double x)
+ {
+ int rounding_mode, round_down;
+@@ -408,7 +408,7 @@ floor (double x)
+ return value;
+ }
+
+-__inline extern double
++__inline double
+ rint (double x)
+ {
+ int rounding_mode, round_nearest;
+@@ -430,7 +430,7 @@ rint (double x)
+ return value;
+ }
+
+-__inline extern double
++__inline double
+ fmod (double x, double y)
+ {
+ double value;
+@@ -442,7 +442,7 @@ fmod (double x, double y)
+ return value;
+ }
+
+-__inline extern double
++__inline double
+ drem (double x, double y)
+ {
+ double value;
+@@ -454,7 +454,7 @@ drem (double x, double y)
+ return value;
+ }
+
+-__inline extern double
++__inline double
+ scalb (double x, int n)
+ {
+ double value;
+@@ -466,7 +466,7 @@ scalb (double x, int n)
+ return value;
+ }
+
+-__inline extern double
++__inline double
+ logb (double x)
+ {
+ double exponent;
+@@ -477,7 +477,7 @@ logb (double x)
+ return exponent;
+ }
+
+-__inline extern double
++__inline double
+ ldexp (double x, int n)
+ {
+ double value;
+@@ -489,7 +489,7 @@ ldexp (double x, int n)
+ return value;
+ }
+
+-__inline extern double
++__inline double
+ frexp (double x, int *exp)
+ {
+ double float_exponent;
+@@ -514,7 +514,7 @@ frexp (double x, int *exp)
+ return mantissa;
+ }
+
+-__inline extern double
++__inline double
+ modf (double x, double *ip)
+ {
+ double temp;
+
+From 443179daa5f06a569a4de7e62c431d787c066f86 Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Sat, 23 Dec 2017 13:18:20 +0100
+Subject: [PATCH 293/303] bump version DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 2d76043c1dd3..e70e15403ebc 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20171221-195003
++20171223-131819
+
+From b5b76e646e60f561e56608ad1839013fcc04d3cc Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 29 Dec 2017 10:20:42 +0100
+Subject: [PATCH 294/303] set -Os as default
+
+---
+ gcc/config.gcc | 1 +
+ libgcc/config.host | 1 +
+ 2 files changed, 2 insertions(+)
+
+diff --git a/gcc/config.gcc b/gcc/config.gcc
+index 0beee32c863c..59df5867053d 100644
+--- gcc/config.gcc
++++ gcc/config.gcc
+@@ -1955,6 +1955,7 @@ m68k*-*-amigaos*)
+ extra_objs=amigaos.o
+ extra_options="${extra_options} m68k/amigaos.opt"
+ gnu_ld=yes
++ CFLAGS="-Os"
+ ;;
+ m68k*-*-netbsdelf*)
+ default_m68k_cpu=68020
+diff --git a/libgcc/config.host b/libgcc/config.host
+index c36e829a5025..0a88fa78c170 100644
+--- libgcc/config.host
++++ libgcc/config.host
+@@ -818,6 +818,7 @@ m32rle-*-linux*)
+ ;;
+ m68k-*-amiga*)
+ tmake_file="$tmake_file m68k/t-glue m68k/t-floatlib soft-fp"
++ CFLAGS="-Os"
+ # tmake_file="$tmake_file m68k/t-glue soft-fp"
+ ;;
+ m68k-*-elf* | fido-*-elf)
+
+From 734f944e12181b7fd69e0447f68f1be7fcd13822 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 29 Dec 2017 10:21:49 +0100
+Subject: [PATCH 295/303] print insn before aborting
+
+---
+ gcc/emit-rtl.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
+index 0fcd9d95e5b4..b2a18e7e4188 100644
+--- gcc/emit-rtl.c
++++ gcc/emit-rtl.c
+@@ -2123,7 +2123,11 @@ change_address_1 (rtx memref, machine_mode mode, rtx addr, int validate,
+ if (validate && !lra_in_progress)
+ {
+ if (reload_in_progress || reload_completed)
+- gcc_assert (memory_address_addr_space_p (mode, addr, as));
++ {
++ bool r = memory_address_addr_space_p (mode, addr, as);
++ if (!r) debug_rtx(addr);
++ gcc_assert (r);
++ }
+ else
+ addr = memory_address_addr_space (mode, addr, as);
+ }
+
+From 765a8c42eee2c949fc5d31b3e4693c8237bdb48b Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 29 Dec 2017 10:22:34 +0100
+Subject: [PATCH 296/303] fix a check with -fbaserel(32)
+
+---
+ gcc/config/m68k/m68k.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
+index 29e2e45df844..4533427db7a7 100644
+--- gcc/config/m68k/m68k.c
++++ gcc/config/m68k/m68k.c
+@@ -1982,10 +1982,12 @@ m68k_legitimate_constant_address_p (rtx x, unsigned int reach, bool strict_p)
+ if (!CONSTANT_ADDRESS_P (x))
+ return false;
+
+- if (flag_pic
++ if (flag_pic && flag_pic < 3
+ && !(strict_p && TARGET_PCREL)
+ && symbolic_operand (x, VOIDmode))
+- return false;
++ {
++ return false;
++ }
+
+ if (M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P && reach > 1)
+ {
+
+From 44cf4734135f00e7949a431a308e5da436735300 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Fri, 29 Dec 2017 10:23:00 +0100
+Subject: [PATCH 297/303] enable multilib
+
+---
+ gcc/config/m68k/t-amigaos | 14 ++++++--------
+ 1 file changed, 6 insertions(+), 8 deletions(-)
+
+diff --git a/gcc/config/m68k/t-amigaos b/gcc/config/m68k/t-amigaos
+index 112d5daa06fb..bf9c5279d04f 100755
+--- gcc/config/m68k/t-amigaos
++++ gcc/config/m68k/t-amigaos
+@@ -10,14 +10,6 @@ amigaos.o: $(srcdir)/config/m68k/amigaos.c $(CONFIG_H)
+
+ #TARGET_LIBGCC2_CFLAGS = -mfixedstack
+
+-# Support for building multiple version of libgcc.
+-
+-LIBGCC_MULTI = .; \
+- libb;@fbaserel \
+- libm020;@m68020 \
+- libb/libm020;@fbaserel@m68020 \
+- libb32/libm020;@fbaserel32@m68020
+-
+ ### begin-GG-local: dynamic libraries
+ # Extra objects that get compiled and linked to collect2
+
+@@ -28,3 +20,9 @@ amigacollect2.o: amigacollect2.c
+ $(CXX) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ -DA2IXDIR_PREFIX=\"$(prefix)/share/a2ixlibrary\" $< $(OUTPUT_OPTION)
+ ### end-GG-local
++
++# Support for building multiple version of libgcc, libquadmath, libobjc and libstdc++-v3
++MULTILIB_OPTIONS = m68020 fbaserel/fbaserel32
++MULTILIB_DIRNAMES = libm020 libb libb32
++MULTILIB_EXTRA_OPTS = noixemul
++MULTILIB_EXCEPTIONS = fbaserel32
+\ No newline at end of file
+
+From e7906b06f6cba077f666b43dfa822c4117078a9a Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Fri, 29 Dec 2017 10:52:57 +0100
+Subject: [PATCH 298/303] bump version DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index e70e15403ebc..1ba74cfc6d61 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20171223-131819
++20171229-105257
+
+From 20fa3b9980630cf21b2a19f6f26e276840e0c7d5 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Wed, 10 Jan 2018 20:37:20 +0100
+Subject: [PATCH 299/303] refs #7: invalidate registers holding a memory
+ referenc if a value is written to that memory reference
+
+---
+ gcc/bbb-opts.c | 34 +++++++++++++++++++++++++++++++---
+ 1 file changed, 31 insertions(+), 3 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 432c9bb4bbd3..ae824bbfbb1a 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -238,13 +238,38 @@ class track_var
+ if (o)
+ assign (o);
+ else
+- for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
++ for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+ {
+ value[i] = 0;
+ mask[i] = 0;
+ }
+ }
+
++ void
++ invalidate_mem(rtx dst) {
++ rtx z = 0;
++ unsigned m = 0;
++ if (extend(&z, &m, GET_MODE(dst), dst))
++ {
++// unsigned hit = 0;
++ for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
++ {
++ if (rtx_equal_p(z, value[i]))
++ {
++ value[i] = 0;
++ mask[i] = 0;
++// hit |= 1<<i;
++ }
++ }
++// if (hit)
++// {
++// fprintf(stderr, "%08x", hit);
++// debug_rtx(z);
++// }
++ }
++ }
++
++
+ rtx
+ get (unsigned regno)
+ {
+@@ -347,7 +372,7 @@ class track_var
+ if (!rtx_equal_p (value[i], o->value[i]))
+ {
+ value[i] = o->value[i] = 0;
+- mask[i] = mask[i] = 0;
++ mask[i] = 0;
+ }
+ }
+ }
+@@ -3940,7 +3965,10 @@ track_regs ()
+ continue;
+
+ if (dregno < 0)
+- continue;
++ {
++ track->invalidate_mem(SET_DEST(set));
++ continue;
++ }
+
+ // operation, autoinf or more than one register used: can't cache
+ if (ii.get_src_op () || ii.get_src_autoinc () || ((ii.get_myuse () - 1) & ii.get_myuse ()))
+
+From 57be9251f4cb7adfd7850d21d7bd77d13474be32 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 11 Jan 2018 20:08:18 +0100
+Subject: [PATCH 300/303] opt_elim_dead_assign checks now if some register
+ contains a value already and uses that reg
+
+---
+ gcc/bbb-opts.c | 41 +++++++++++++++++++++++++++++++----------
+ 1 file changed, 31 insertions(+), 10 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index ae824bbfbb1a..3235c84deb4b 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -223,10 +223,11 @@ class track_var
+ *z = gen_rtx_MEM (GET_MODE(x), m);
+ return true;
+ }
++ default:
++ return false;
+ }
+- return false;
++ break;
+ }
+-
+ default:
+ return false;
+ }
+@@ -245,27 +246,36 @@ class track_var
+ }
+ }
+
++ int find_alias(rtx src)
++ {
++ rtx z = 0;
++ unsigned m = 0;
++ if (extend(&z, &m, GET_MODE(src), src))
++ {
++ for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
++ {
++ // do not alias small int value from -128 ... 127
++ if (rtx_equal_p(z, value[i]) && (GET_CODE(z) != CONST_INT || INTVAL(z) > 127 || INTVAL(z) < -128))
++ return i;
++ }
++ }
++ return -1;
++ }
+ void
+- invalidate_mem(rtx dst) {
++ invalidate_mem(rtx dst)
++ {
+ rtx z = 0;
+ unsigned m = 0;
+ if (extend(&z, &m, GET_MODE(dst), dst))
+ {
+-// unsigned hit = 0;
+ for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+ {
+ if (rtx_equal_p(z, value[i]))
+ {
+ value[i] = 0;
+ mask[i] = 0;
+-// hit |= 1<<i;
+ }
+ }
+-// if (hit)
+-// {
+-// fprintf(stderr, "%08x", hit);
+-// debug_rtx(z);
+-// }
+ }
+ }
+
+@@ -4038,6 +4048,17 @@ opt_elim_dead_assign (int blocked_regno)
+ continue;
+ }
+
++ // is there a register holding that value?
++ if (!ii.get_src_reg ())
++ {
++ int aliasRegno = track->find_alias(src);
++ if (aliasRegno >= 0 && aliasRegno != ii.get_dst_regno())
++ {
++ log ("(e) %d: replace load with %s\n", index, reg_names[aliasRegno]);
++ validate_change (ii.get_insn(), &SET_SRC(set), gen_rtx_REG(ii.get_mode(), aliasRegno), 0);
++ ++change_count;
++ }
++ }
+ }
+ }
+ return change_count;
+
+From 03065de1585bae453567dbf1c2352794fac793d1 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 11 Jan 2018 20:09:01 +0100
+Subject: [PATCH 301/303] reg rename may use the starting used register if it's
+ dead there (Jim)
+
+---
+ gcc/bbb-opts.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 3235c84deb4b..2be2afe83c77 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -2332,6 +2332,10 @@ opt_reg_rename (void)
+ /* get the mask for free registers. */
+ unsigned mask = ii.get_free_mask ();
+
++ /* the mask contains the current src register. Add this register to the mask if it's dead here. */
++ if (ii.get_src_reg() && is_reg_dead(ii.get_src_regno(), index))
++ mask |= ii.get_use();
++
+ /* do not use a4 if compiling baserel */
+ if (flag_pic >= 3)
+ mask &= ~(1 << PIC_REG);
+
+From 14767273a413e13794aeec098ee0c54acce1b9d4 Mon Sep 17 00:00:00 2001
+From: bebbo <bebbo@bejy.net>
+Date: Thu, 11 Jan 2018 21:36:13 +0100
+Subject: [PATCH 302/303] change register order - prefer ax over dx to avoid
+ address calculation in dx regs, improve opt_elim_dead_assign() to eliminate
+ self assignments
+
+---
+ gcc/bbb-opts.c | 50 ++++++++++++++++++++++++++++----------------------
+ gcc/config/m68k/m68k.h | 16 ++++++++++++++--
+ 2 files changed, 42 insertions(+), 24 deletions(-)
+
+diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c
+index 2be2afe83c77..9e989e9b1ec0 100755
+--- gcc/bbb-opts.c
++++ gcc/bbb-opts.c
+@@ -246,31 +246,32 @@ class track_var
+ }
+ }
+
+- int find_alias(rtx src)
++ int
++ find_alias (rtx src)
+ {
+ rtx z = 0;
+ unsigned m = 0;
+- if (extend(&z, &m, GET_MODE(src), src))
++ if (extend (&z, &m, GET_MODE(src), src))
+ {
+ for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+ {
+ // do not alias small int value from -128 ... 127
+- if (rtx_equal_p(z, value[i]) && (GET_CODE(z) != CONST_INT || INTVAL(z) > 127 || INTVAL(z) < -128))
++ if (rtx_equal_p (z, value[i]) && (GET_CODE(z) != CONST_INT || INTVAL(z) > 127 || INTVAL(z) < -128))
+ return i;
+ }
+ }
+ return -1;
+ }
+ void
+- invalidate_mem(rtx dst)
++ invalidate_mem (rtx dst)
+ {
+ rtx z = 0;
+ unsigned m = 0;
+- if (extend(&z, &m, GET_MODE(dst), dst))
++ if (extend (&z, &m, GET_MODE(dst), dst))
+ {
+ for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+ {
+- if (rtx_equal_p(z, value[i]))
++ if (rtx_equal_p (z, value[i]))
+ {
+ value[i] = 0;
+ mask[i] = 0;
+@@ -279,7 +280,6 @@ class track_var
+ }
+ }
+
+-
+ rtx
+ get (unsigned regno)
+ {
+@@ -1517,7 +1517,7 @@ find_reg_by_no (rtx x, unsigned oldregno)
+ for (int j = XVECLEN (x, i) - 1; j >= 0; j--)
+ {
+ rtx z = XVECEXP(x, i, j);
+- rtx r = find_reg_by_no(z, oldregno);
++ rtx r = find_reg_by_no (z, oldregno);
+ if (r)
+ return r;
+ }
+@@ -2333,8 +2333,8 @@ opt_reg_rename (void)
+ unsigned mask = ii.get_free_mask ();
+
+ /* the mask contains the current src register. Add this register to the mask if it's dead here. */
+- if (ii.get_src_reg() && is_reg_dead(ii.get_src_regno(), index))
+- mask |= ii.get_use();
++ if (ii.get_src_reg () && is_reg_dead (ii.get_src_regno (), index))
++ mask |= ii.get_use ();
+
+ /* do not use a4 if compiling baserel */
+ if (flag_pic >= 3)
+@@ -2497,11 +2497,11 @@ opt_reg_rename (void)
+ rtx_insn * insn = rr.get_insn ();
+
+ /* get rename locations. */
+- rtx from = find_reg_by_no(PATTERN (insn), oldregno);
++ rtx from = find_reg_by_no (PATTERN (insn), oldregno);
+ if (from)
+ {
+- rtx to = gen_raw_REG(GET_MODE(from), newregno);
+- validate_replace_rtx_group(from, to, insn);
++ rtx to = gen_raw_REG (GET_MODE(from), newregno);
++ validate_replace_rtx_group (from, to, insn);
+
+ positions.push_back (*i);
+ }
+@@ -3945,11 +3945,17 @@ track_regs ()
+ if (ii.is_compare ())
+ continue;
+
+- int dregno = ii.get_dst_regno ();
+- track->clear (ii.get_mode (), dregno, index);
+-
+ unsigned def = ii.get_def () & 0xffffff;
+- track->clear_for_mask (def, index);
++ if (def)
++ {
++ // more than one register set? or mask from clobber?
++ if (((def - 1) & def) || !ii.get_dst_reg ())
++ track->clear_for_mask (def, index);
++ }
++ // do not clear if self assigned
++ int dregno = ii.get_dst_regno ();
++ if (dregno != ii.get_src_regno ())
++ track->clear (ii.get_mode (), dregno, index);
+
+ if (ii.is_call ())
+ {
+@@ -3980,7 +3986,7 @@ track_regs ()
+
+ if (dregno < 0)
+ {
+- track->invalidate_mem(SET_DEST(set));
++ track->invalidate_mem (SET_DEST(set));
+ continue;
+ }
+
+@@ -4031,7 +4037,7 @@ opt_elim_dead_assign (int blocked_regno)
+
+ // check for redundant load
+ if (ii.get_src_op () == 0 && ii.get_dst_reg () && ii.get_dst_regno () != blocked_regno
+- && !ii.is_myuse (ii.get_dst_regno ()))
++ && (!ii.is_myuse (ii.get_dst_regno ()) || ii.get_dst_regno () == ii.get_src_regno ()))
+ {
+ track_var * track = ii.get_track_var ();
+
+@@ -4055,11 +4061,11 @@ opt_elim_dead_assign (int blocked_regno)
+ // is there a register holding that value?
+ if (!ii.get_src_reg ())
+ {
+- int aliasRegno = track->find_alias(src);
+- if (aliasRegno >= 0 && aliasRegno != ii.get_dst_regno())
++ int aliasRegno = track->find_alias (src);
++ if (aliasRegno >= 0 && aliasRegno != ii.get_dst_regno ())
+ {
+ log ("(e) %d: replace load with %s\n", index, reg_names[aliasRegno]);
+- validate_change (ii.get_insn(), &SET_SRC(set), gen_rtx_REG(ii.get_mode(), aliasRegno), 0);
++ validate_change (ii.get_insn (), &SET_SRC(set), gen_rtx_REG (ii.get_mode (), aliasRegno), 0);
+ ++change_count;
+ }
+ }
+diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h
+index 6cdc635d4df3..278b048ae237 100644
+--- gcc/config/m68k/m68k.h
++++ gcc/config/m68k/m68k.h
+@@ -378,13 +378,25 @@ along with GCC; see the file COPYING3. If not see
+ /* Arg pointer. */ \
+ 1 }
+
++#if 0
+ #define REG_ALLOC_ORDER \
+ { /* d0/d1/a0/a1 */ \
+ 0, 1, 8, 9, \
+ /* d2-d7 */ \
+- 2, 3, 4, 5, 6, 7, \
++ 2, 10, 3, 11, 4, 5, 6, 7, \
+ /* a2-a7/arg */ \
+- 10, 11, 12, 13, 14, 15, 24, \
++ 12, 13, 14, 15, 24, \
++ /* fp0-fp7 */ \
++ 16, 17, 18, 19, 20, 21, 22, 23\
++}
++#endif
++#define REG_ALLOC_ORDER \
++{ /* d0/d1/a0/a1 */ \
++ 0, 8, 9, 1, \
++ /* a2-a7 */ \
++ 10, 11, 12, 13, 14, 15, \
++ /* d2-d7/arg */ \
++ 2, 3, 4, 5, 6, 7, 24, \
+ /* fp0-fp7 */ \
+ 16, 17, 18, 19, 20, 21, 22, 23\
+ }
+
+From 359713c99b0cbf7744ad3158929c53fb304e3ce4 Mon Sep 17 00:00:00 2001
+From: fautomat <automat@franke.ms>
+Date: Thu, 11 Jan 2018 22:28:38 +0100
+Subject: [PATCH 303/303] bump version DATESTAMP
+
+---
+ gcc/DATESTAMP | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
+index 1ba74cfc6d61..97461d26bd27 100644
+--- gcc/DATESTAMP
++++ gcc/DATESTAMP
+@@ -1 +1 @@
+-20171229-105257
++20180111-222838
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gmp-configure.p b/m68k-unknown-amigaos/recipes/patches/gcc/gmp-configure.p
deleted file mode 100644
index a8ac807..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/gmp-configure.p
+++ /dev/null
@@ -1,11 +0,0 @@
---- gmp/configure.orig 2012-08-17 18:03:57.000000000 +0100
-+++ gmp/configure 2012-08-17 18:04:17.000000000 +0100
-@@ -30006,8 +30006,6 @@
- echo "define(<M4WRAP_SPURIOUS>,<$gmp_cv_m4_m4wrap_spurious>)" >> $gmp_tmpconfigm4
-
-
--else
-- M4=m4-not-needed
- fi
-
- # Only do the GMP_ASM checks if there's a .S or .asm wanting them.
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/include.filenames.h.p b/m68k-unknown-amigaos/recipes/patches/gcc/include.filenames.h.p
deleted file mode 100644
index a9d5548..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/include.filenames.h.p
+++ /dev/null
@@ -1,14 +0,0 @@
---- gcc-3.4.6/include/filenames.h 2003-07-01 22:29:16.000000000 +0200
-+++ include/filenames.h 2013-05-19 20:23:32.000000000 +0200
-@@ -43,7 +43,11 @@
- #else /* not DOSish */
-
- #define IS_DIR_SEPARATOR(c) ((c) == '/')
-+#if !defined(__amigaos__)
- #define IS_ABSOLUTE_PATH(f) (IS_DIR_SEPARATOR((f)[0]))
-+#else
-+#define IS_ABSOLUTE_PATH(f) (IS_DIR_SEPARATOR((f)[0]) || strchr((f), VOL_SEPARATOR))
-+#endif
- #define FILENAME_CMP(s1, s2) strcmp(s1, s2)
-
- #endif /* not DOSish */
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/libiberty.configure.p b/m68k-unknown-amigaos/recipes/patches/gcc/libiberty.configure.p
deleted file mode 100644
index 928f83e..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/libiberty.configure.p
+++ /dev/null
@@ -1,105 +0,0 @@
---- gcc-3.4.6/libiberty/configure 2003-10-01 19:11:29.000000000 +0200
-+++ libiberty/configure 2013-05-19 20:23:32.000000000 +0200
-@@ -347,6 +347,10 @@
- includedir='${prefix}/include'
- oldincludedir='/usr/include'
- infodir='${prefix}/info'
-+guidedir='${prefix}/guide'
-+htmldir='${prefix}/html'
-+psdir='${prefix}/ps'
-+dvidir='${prefix}/dvi'
- mandir='${prefix}/man'
-
- ac_prev=
-@@ -450,6 +454,26 @@
- -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
- infodir=$ac_optarg ;;
-
-+ -guidedir | --guidedir | --guidedi | --guided | --guide | --gui)
-+ ac_prev=guidedir ;;
-+ -guidedir=* | --guidedir=* | --guidedi=* | --guided=* | --guide=* |--gui=*)
-+ guidedir=$ac_optarg ;;
-+
-+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm)
-+ ac_prev=htmldir ;;
-+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* |--htm=*)
-+ htmldir=$ac_optarg ;;
-+
-+ -psdir | --psdir | --psdi | --psd | --ps)
-+ ac_prev=psdir ;;
-+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
-+ psdir=$ac_optarg ;;
-+
-+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
-+ ac_prev=dvidir ;;
-+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* |--dv=*)
-+ dvidir=$ac_optarg ;;
-+
- -libdir | --libdir | --libdi | --libd)
- ac_prev=libdir ;;
- -libdir=* | --libdir=* | --libdi=* | --libd=*)
-@@ -825,6 +849,10 @@
- --includedir=DIR C header files [PREFIX/include]
- --oldincludedir=DIR C header files for non-gcc [/usr/include]
- --infodir=DIR info documentation [PREFIX/info]
-+ --guidedir=DIR Amigaguide documentation in DIR [PREFIX/guide]
-+ --htmldir=DIR HTML documentation in DIR [PREFIX/html]
-+ --psdir=DIR postscript documentation in DIR [PREFIX/ps]
-+ --dvidir=DIR TeX dvi documentation in DIR [PREFIX/dvi]
- --mandir=DIR man documentation [PREFIX/man]
- _ACEOF
-
-@@ -3322,7 +3350,7 @@
- # Account for people who put trailing slashes in PATH elements.
- case $as_dir/ in
- ./ | .// | /cC/* | \
-- /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
-+ /etc/* | /c/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
- /usr/ucb/* ) ;;
- *)
- # OSF1 and SCO ODT 3.0 have their own names for install.
-@@ -5108,6 +5136,12 @@
-
- sparc_address_test (0);
-
-+#ifdef __amigaos__
-+ /* Force this test to succeed for AmigaOS, which has a fairly good
-+ vfork() emulation, but doesn't support fork() at all. -fnf */
-+ exit (0);
-+#endif
-+
- child = vfork ();
-
- if (child == 0) {
-@@ -5208,6 +5242,11 @@
- #define HAVE_WORKING_FORK 1
- _ACEOF
-
-+else
-+ cat >> confdefs.h <<\EOF
-+#define HAVE_VFORK 1
-+EOF
-+
- fi
-
- if test $ac_cv_func_vfork_works = no; then
-@@ -6761,6 +6800,10 @@
- s,@includedir@,$includedir,;t t
- s,@oldincludedir@,$oldincludedir,;t t
- s,@infodir@,$infodir,;t t
-+s,@guidedir@,$guidedir,;t t
-+s,@htmldir@,$htmldir,;t t
-+s,@psdir@,$psdir,;t t
-+s,@dvidir@,$dvidir,;t t
- s,@mandir@,$mandir,;t t
- s,@build_alias@,$build_alias,;t t
- s,@host_alias@,$host_alias,;t t
-@@ -7297,7 +7340,7 @@
- case $ac_dest in
- default ) test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h
- if test -n "$CONFIG_FILES"; then
-- if test -n "${with_build_subdir}" || test -n "${with_target_subdir}"; then
-+ if test -n "${with_target_subdir}"; then
- # FIXME: We shouldn't need to set ac_file
- ac_file=Makefile
- LD="${ORIGINAL_LD_FOR_MULTILIBS}"
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/libiberty.lbasename.c.p b/m68k-unknown-amigaos/recipes/patches/gcc/libiberty.lbasename.c.p
deleted file mode 100644
index 735ca77..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/libiberty.lbasename.c.p
+++ /dev/null
@@ -1,13 +0,0 @@
---- gcc-3.4.6/libiberty/lbasename.c 2003-12-22 20:21:37.000000000 +0100
-+++ libiberty/lbasename.c 2013-05-19 20:23:32.000000000 +0200
-@@ -42,6 +42,10 @@
- #include "safe-ctype.h"
- #include "filenames.h"
-
-+#ifdef __amigaos__
-+#define VOL_SEPARATOR ':'
-+#endif
-+
- const char *
- lbasename (name)
- const char *name;
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/libiberty.make-temp-file.c.p b/m68k-unknown-amigaos/recipes/patches/gcc/libiberty.make-temp-file.c.p
deleted file mode 100644
index fec49da..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/libiberty.make-temp-file.c.p
+++ /dev/null
@@ -1,27 +0,0 @@
---- gcc-3.4.6/libiberty/make-temp-file.c 2001-10-17 23:15:41.000000000 +0200
-+++ libiberty/make-temp-file.c 2013-05-19 20:23:32.000000000 +0200
-@@ -50,6 +50,10 @@
- #define DIR_SEPARATOR '/'
- #endif
-
-+#ifdef __amigaos__
-+#define VOL_SEPARATOR ':'
-+#endif
-+
- /* Name of temporary file.
- mktemp requires 6 trailing X's. */
- #define TEMP_FILE "ccXXXXXX"
-@@ -126,8 +130,13 @@
- len = strlen (base);
- tmpdir = xmalloc (len + 2);
- strcpy (tmpdir, base);
-+#ifdef VOL_SEPARATOR
-+ if (tmpdir[len-1] != DIR_SEPARATOR && tmpdir[len-1] != VOL_SEPARATOR)
-+#endif
-+{
- tmpdir[len] = DIR_SEPARATOR;
- tmpdir[len+1] = '\0';
-+}
-
- memoized_tmpdir = tmpdir;
- return tmpdir;
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/libiberty.pex-unix.c.p b/m68k-unknown-amigaos/recipes/patches/gcc/libiberty.pex-unix.c.p
deleted file mode 100644
index b90f69e..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/libiberty.pex-unix.c.p
+++ /dev/null
@@ -1,13 +0,0 @@
---- gcc-3.4.6/libiberty/pex-unix.c 2003-01-24 21:02:11.000000000 +0100
-+++ libiberty/pex-unix.c 2013-05-19 20:23:32.000000000 +0200
-@@ -44,6 +44,10 @@
- #define waitpid(pid, status, flags) wait(status)
- #endif
-
-+#ifdef __amigaos__
-+#define fork() vfork()
-+#endif
-+
- extern int execv ();
- extern int execvp ();
-
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/libiberty.strsignal.c.p b/m68k-unknown-amigaos/recipes/patches/gcc/libiberty.strsignal.c.p
deleted file mode 100644
index db4ce9e..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/libiberty.strsignal.c.p
+++ /dev/null
@@ -1,13 +0,0 @@
---- gcc-3.4.6/libiberty/strsignal.c 2003-04-15 22:36:33.000000000 +0200
-+++ libiberty/strsignal.c 2013-05-19 20:23:32.000000000 +0200
-@@ -558,8 +558,8 @@
-
- void
- psignal (signo, message)
-- unsigned signo;
-- char *message;
-+ unsigned int signo;
-+ const char *message;
- {
- if (signal_names == NULL)
- {
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/libstdc++-v3.config.cpu.m68k.atomicity.h.p b/m68k-unknown-amigaos/recipes/patches/gcc/libstdc++-v3.config.cpu.m68k.atomicity.h.p
deleted file mode 100644
index 192d911..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/libstdc++-v3.config.cpu.m68k.atomicity.h.p
+++ /dev/null
@@ -1,25 +0,0 @@
---- gcc-3.4.6/libstdc++-v3/config/cpu/m68k/atomicity.h 2004-03-18 18:36:28.000000000 +0100
-+++ libstdc++-v3/config/cpu/m68k/atomicity.h 2013-05-19 20:23:32.000000000 +0200
-@@ -31,7 +31,21 @@
-
- namespace __gnu_cxx
- {
--#if ( defined(__mc68020__) || defined(__mc68030__) \
-+#if defined(__amigaos__)
-+
-+ _Atomic_word
-+ __attribute__ ((__unused__))
-+ __exchange_and_add (volatile _Atomic_word *__mem, int __val)
-+ {
-+ _Atomic_word __result;
-+
-+ __result = *__mem;
-+ *__mem = __result + __val;
-+
-+ return __result;
-+ }
-+
-+#elif ( defined(__mc68020__) || defined(__mc68030__) \
- || defined(__mc68040__) || defined(__mc68060__) ) \
- && !defined(__mcpu32__)
- // These variants support compare-and-swap.
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/libstdc++-v3.configure.p b/m68k-unknown-amigaos/recipes/patches/gcc/libstdc++-v3.configure.p
deleted file mode 100644
index d0f9e88..0000000
--- a/m68k-unknown-amigaos/recipes/patches/gcc/libstdc++-v3.configure.p
+++ /dev/null
@@ -1,13 +0,0 @@
---- gcc-3.4.6/libstdc++-v3/configure 2013-05-19 20:08:06.000000000 +0200
-+++ libstdc++-v3/configure 2013-05-19 20:23:32.000000000 +0200
-@@ -31093,6 +31093,10 @@
-
- # Base decisions on target environment.
- case "${host}" in
-+ m68k-*-amigaos*)
-+ #os_include_dir="os/newlib"
-+ ;;
-+
- *-darwin*)
- # Darwin versions vary, but the linker should work in a cross environment,
- # so we just check for all the features here.