From 8614f549b79ac6d9d079efc85a735d0c092ff3e8 Mon Sep 17 00:00:00 2001 From: Chris Young Date: Fri, 12 Jan 2018 23:21:58 +0000 Subject: Update to gcc 6.3 using bebbo's patches (generated from github.com/bebbo/gcc) --- m68k-unknown-amigaos/Makefile | 2 +- .../recipes/patches/gcc/configure.p | 12 - .../recipes/patches/gcc/gcc.Makefile.in.p | 133 - .../recipes/patches/gcc/gcc.c-decl.c.p | 87 - .../recipes/patches/gcc/gcc.c-incpath.c.p | 19 - .../recipes/patches/gcc/gcc.c-parse.in.p | 223 - .../recipes/patches/gcc/gcc.c-tree.h.p | 13 - .../recipes/patches/gcc/gcc.calls.c.p | 24 - .../recipes/patches/gcc/gcc.collect2.c.p | 200 - .../recipes/patches/gcc/gcc.common.opt.p | 17 - .../recipes/patches/gcc/gcc.config.gcc.p | 17 - .../recipes/patches/gcc/gcc.config.host-linux.c.p | 11 - .../recipes/patches/gcc/gcc.config.host.p | 14 - .../patches/gcc/gcc.config.m68k.m68k-protos.h.p | 14 - .../recipes/patches/gcc/gcc.config.m68k.m68k.c.p | 513 - .../recipes/patches/gcc/gcc.config.m68k.m68k.h.p | 175 - .../recipes/patches/gcc/gcc.config.m68k.m68k.md.p | 82 - .../recipes/patches/gcc/gcc.configure.ac.p | 35 - .../recipes/patches/gcc/gcc.configure.p | 61 - .../recipes/patches/gcc/gcc.cppfiles.c.p | 48 - .../recipes/patches/gcc/gcc.defaults.h.p | 13 - .../recipes/patches/gcc/gcc.fixinc.mkfixinc.sh.p | 10 - .../recipes/patches/gcc/gcc.flow.c.p | 19 - .../recipes/patches/gcc/gcc.function.c.p | 31 - .../recipes/patches/gcc/gcc.function.h.p | 11 - .../recipes/patches/gcc/gcc.gcc.c.p | 63 - .../recipes/patches/gcc/gcc.ginclude.stdarg.h.p | 20 - .../recipes/patches/gcc/gcc.loop.c.p | 13 - .../recipes/patches/gcc/gcc.mklibgcc.in.p | 13 - .../recipes/patches/gcc/gcc.opts.c.p | 26 - .../recipes/patches/gcc/gcc.rtl.h.p | 11 - .../recipes/patches/gcc/gcc.toplev.c.p | 11 - m68k-unknown-amigaos/recipes/patches/gcc/gcc6.p | 42963 +++++++++++++++++++ .../recipes/patches/gcc/gmp-configure.p | 11 - .../recipes/patches/gcc/include.filenames.h.p | 14 - .../recipes/patches/gcc/libiberty.configure.p | 105 - .../recipes/patches/gcc/libiberty.lbasename.c.p | 13 - .../patches/gcc/libiberty.make-temp-file.c.p | 27 - .../recipes/patches/gcc/libiberty.pex-unix.c.p | 13 - .../recipes/patches/gcc/libiberty.strsignal.c.p | 13 - .../gcc/libstdc++-v3.config.cpu.m68k.atomicity.h.p | 25 - .../recipes/patches/gcc/libstdc++-v3.configure.p | 13 - 42 files changed, 42964 insertions(+), 2174 deletions(-) delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/configure.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.Makefile.in.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.c-decl.c.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.c-incpath.c.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.c-parse.in.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.c-tree.h.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.calls.c.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.collect2.c.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.common.opt.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.gcc.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.host-linux.c.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.host.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.m68k.m68k-protos.h.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.m68k.m68k.c.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.m68k.m68k.h.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.m68k.m68k.md.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.configure.ac.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.configure.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.cppfiles.c.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.defaults.h.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.fixinc.mkfixinc.sh.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.flow.c.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.function.c.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.function.h.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.gcc.c.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.ginclude.stdarg.h.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.loop.c.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.mklibgcc.in.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.opts.c.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.rtl.h.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc.toplev.c.p create mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc6.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gmp-configure.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/include.filenames.h.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/libiberty.configure.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/libiberty.lbasename.c.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/libiberty.make-temp-file.c.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/libiberty.pex-unix.c.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/libiberty.strsignal.c.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/libstdc++-v3.config.cpu.m68k.atomicity.h.p delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/libstdc++-v3.configure.p 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); -+ { $$ = 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); } -+ { $$ = start_struct (UNION_TYPE, $2); } - component_decl_list '}' maybe_attribute - { $$ = finish_struct ($4, nreverse ($5), - chainon ($1, $7)); } -@@ -1750,12 +1750,12 @@ structsp_attr: - nreverse ($3), chainon ($1, $5)); - } - | enum_head identifier '{' -- { $$ = start_enum ($2); } -+ { $$ = start_enum ($2); } - enumlist maybecomma_warn '}' maybe_attribute - { $$ = finish_enum ($4, nreverse ($5), - chainon ($1, $8)); } - | enum_head '{' -- { $$ = start_enum (NULL_TREE); } -+ { $$ = start_enum (NULL_TREE); } - enumlist maybecomma_warn '}' maybe_attribute - { $$ = finish_enum ($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=' 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 +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 ++//+ ++//+ * 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=' 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 ++. */ ++ ++#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 ++#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 and the C++ include file , where the C++ ++ include file dir is searched first and thus causes includes of ++ to include 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 +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 @@ ++ ++ ++ gcc-6 ++ ++ ++ ++ ++ ++ ++ ++ + +From c81713312a097d40d212a5ac5bce13b1aff7b226 Mon Sep 17 00:00:00 2001 +From: bebbo +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 + #include + + // For 8.22.1/1 (see C99, Notes 219, 220, 222) + +From 8a098e5a7bb1c14c1afa7946dce4416596418e8a Mon Sep 17 00:00:00 2001 +From: bebbo +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 ++#endif + #include + + // For 8.22.1/1 (see C99, Notes 219, 220, 222) + +From a3e959953b7386e1576961fb4666f704b2edac7f Mon Sep 17 00:00:00 2001 +From: bebbo +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 ++ . */ ++ ++/** ++ * 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 ++#include ++ ++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 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 +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 reg_reg; ++ std::vector 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::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::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 +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 +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 +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 + #include + +-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 insns; ++static std::vector jumps; ++static std::map insn2index; ++static std::vector 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> todo; ++ todo.push_back (std::make_pair (insns.size () - 1, ii)); ++ ++ int pass = 0; ++ while (!todo.empty ()) ++ { ++ std::pair 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::iterator i = jumps.begin (); i != jumps.end (); ++i) ++ { ++ if (JUMP_LABEL(*i) == insn) ++ { ++ std::map::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 reg_reg; ++ unsigned current_label_index; ++ std::vector reg_reg; ++ std::vector 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::iterator i = reg_reg.begin (); +- i != reg_reg.end () && i + 1 != reg_reg.end ();) ++ for (std::vector::iterator i = reg_reg.begin (); i != reg_reg.end () && i + 1 != reg_reg.end (); ++ ) + { + bool inc = true; +- for (std::vector::iterator j = i + 1; j != reg_reg.end ();) ++ for (std::vector::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 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::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 +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 +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 +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 + + /* 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> todo; + todo.push_back (std::make_pair (insns.size () - 1, ii)); + +@@ -236,53 +247,40 @@ filter_insns () + if (JUMP_LABEL(*i) == insn) + { + std::map::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 +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 + #include + +-/* 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 insns; + static std::vector jumps; + static std::map insn2index; + static std::vector 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::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 +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 todo; ++ std::vector 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::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 +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::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 todo; + std::vector 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 +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 +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 +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 + #include + +@@ -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 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 found; ++ std::vector 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::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::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 +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 insns; ++static std::vector temp; + static std::vector jumps; + static std::map insn2index; + static std::vector 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 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 found; +- std::vector 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::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 regs; ++ std::vector 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::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 +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 + #include + +@@ -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, ""); ++ 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 found; ++ std::vector 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::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::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 +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 +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 +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 + #include + ++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, ""); ++ 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, ""); +- 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 found; +- std::vector 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::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::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 +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 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/.project b/.project +index ab5c4b198d08..22b8c5a11f48 100644 +--- .project ++++ .project +@@ -5,7 +5,23 @@ + + + ++ ++ org.eclipse.cdt.managedbuilder.core.genmakebuilder ++ clean,full,incremental, ++ ++ ++ ++ ++ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder ++ full,incremental, ++ ++ ++ + + ++ org.eclipse.cdt.core.cnature ++ org.eclipse.cdt.core.ccnature ++ org.eclipse.cdt.managedbuilder.core.managedBuildNature ++ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + +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 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +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 +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 +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 +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 +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 +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 = ®_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 +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 +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 ++#include + #include + + 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 insns; ++static std::vector proepilogue; + static std::vector temp; + static std::vector jumps; + static std::map 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 found; ++ std::vector 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::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::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 = ®_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 +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> & 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> 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 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::iterator i = found.begin (); i != found.end (); ++i) ++ /* check the renamed insns. */ ++ std::vector> locs; ++ bool ok = true; ++ std::vector patch; ++ for (std::set::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>::iterator j = locs.begin (); j != locs.end (); ++j) ++ { ++ debug_rtx (*j->first); ++ debug_rtx (j->second); ++ } ++ ok = false; ++ } ++ ++ for (std::vector>::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>::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::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 +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 +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> & loc, rtx x, unsigned oldregno, unsigned newregno) ++temp_reg_rename (std::vector> & loc, rtx x, unsigned oldregno, unsigned newregno) + { + RTX_CODE code = GET_CODE(x); + +@@ -322,44 +349,17 @@ validate_rename (std::vector> & 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> locs; ++ std::vector> patch; + bool ok = true; +- std::vector patch; ++ + for (std::set::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>::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>::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>::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::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>::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 +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> & loc, rtx x, unsigned oldre + * Collect some data. + */ + static std::vector insns; +-static std::vector proepilogue; ++static std::vector proepilogue; + static std::vector temp; + static std::vector jumps; + static std::map 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> 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>::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 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::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::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 +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 +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 +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> & loc, rtx x, unsigned oldregno, unsigned newregno) ++temp_reg_rename (std::vector > & 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> todo; ++ std::vector > 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> locs; +- std::vector> patch; ++ std::vector > locs; ++ std::vector > patch; + bool ok = true; + + for (std::set::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>::iterator j = locs.begin (); j != locs.end (); ++j) ++ for (std::vector >::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>::iterator j = patch.begin (); j != patch.end (); ++j) ++ for (std::vector >::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 +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 +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 +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 +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 +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 +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 > & 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 & 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::iterator i = jumps.begin (); i != jumps.end (); ++i) ++ { ++ if (JUMP_LABEL(*i) == insn) ++ { ++ std::map::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::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 >::iterator j = patch.begin (); j != patch.end (); ++j) + +From ee7031d5d1442ca1e933b3cb029f91ba1534354d Mon Sep 17 00:00:00 2001 +From: bebbo +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 & 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 +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 +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 found; ++ /* first = pos to start, second indicates to treat def as use. */ + std::vector todo; ++ std::set 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::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::iterator i = jumps.begin (); i != jumps.end (); ++i) + { +- std::map::iterator j = insn2index.find (*i); +- if (j == insn2index.end ()) +- continue; ++ if (JUMP_LABEL(*i) == insn) ++ { ++ std::map::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::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::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 +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 +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 & 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 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 fixups; ++ std::vector::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::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 +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 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::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 +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 +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 + #include + #include + +-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 +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 +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 > & loc, rtx x, unsigned oldr + /* + * Collect some data. + */ +-static std::vector insns; +-static std::vector proepilogue; +-static std::vector temp; ++static std::vector infos; + static std::vector jumps; + static std::map insn2index; +-static std::vector infos; + + /* + * Reset collected data. +@@ -500,8 +536,6 @@ static std::vector 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 > 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::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 & 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 todo; + std::set 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::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::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 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::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 todo; + std::vector 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 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::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::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 +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 +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 > & loc, rtx x, unsigned oldr + */ + static std::vector infos; + static std::vector jumps; +-static std::map insn2index; ++static std::map 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::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::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::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::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 +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 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 +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 +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 +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 +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 @@ + + + +@@ -56,12 +57,13 @@ + + + + + +- +@@ -115,6 +118,7 @@ + + + +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 +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::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::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 +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 +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 jumps; + static std::map 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 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 +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::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 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 +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 +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 @@ + + + ++ + + + +@@ -58,6 +59,7 @@ + + + ++ + + + +@@ -106,6 +108,7 @@ + + + ++ + + + +@@ -119,6 +122,7 @@ + + + ++ + + + +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 todo; +- std::vector 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 +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 +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 > & loc, rtx x, unsigned oldr + static std::vector infos; + static std::vector jumps; + static std::map insn2index; ++typedef std::vector::iterator insn_info_iterator; ++typedef std::vector::iterator rtx_insn_iterator; ++typedef std::map::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::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::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::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 +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 +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 +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 +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 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 +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 +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 +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, ""); + 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 regs; + std::vector 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 +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 +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=' 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=' 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 +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 +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 > & loc, rtx x, unsigned oldr + * Collect some data. + */ + static std::vector infos; +-static std::vector jumps; +-static std::map insn2index; + typedef std::vector::iterator insn_info_iterator; +-typedef std::vector::iterator rtx_insn_iterator; ++ ++static std::multimap label2jump; ++typedef std::multimap::iterator l2j_iterator; ++ ++static std::map insn2index; + typedef std::map::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 +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 +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 +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 +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 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 +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 +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 +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 +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 +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::iterator l2j_iterator; + static std::map insn2index; + typedef std::map::iterator i2i_iterator; + ++static std::set returns; ++typedef std::set::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 > 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 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 +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 +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 > & loc, rtx x, unsigned oldr + static std::vector infos; + typedef std::vector::iterator insn_info_iterator; + ++// insn->u2.insn_uid -> rtx_insn * + static std::multimap label2jump; + typedef std::multimap::iterator l2j_iterator; + +-static std::map insn2index; ++// index -> index ++static std::multimap jump2label; ++typedef std::multimap::iterator j2l_iterator; ++ ++static std::map insn2info; + typedef std::map::iterator i2i_iterator; + + static std::set 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 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 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::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 +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 +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 +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 +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 regs; + std::vector 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 +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 > todo; ++ std::set 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 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::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 +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 @@ + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + ++ ++ ++ build-gcc ++ 2 ++ D:/develop/workspaces/c1/amigaos-cross-toolchain/.build-m68k/build/gcc-6 ++ ++ + +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 @@ + + + +- ++ + + + +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 +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 +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 +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 +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 +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 +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 +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 todo; +- todo.push_back (0); ++ std::set 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 +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 todo; ++ std::set todo; + std::set 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 +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 +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 +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 +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 +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 +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::iterator j2l_iterator; + static std::map insn2info; + typedef std::map::iterator i2i_iterator; + +-static std::set returns; ++static std::set scan_starts; + typedef std::set::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 todo; +- for (su_iterator i = returns.begin (); i != returns.end (); ++i) +- todo.insert (*i); ++ std::set & 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 & 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::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 +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 & 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 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 +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 +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 +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 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 +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 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 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::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::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::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 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::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 +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 +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 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 todo; +- todo.insert (0); ++// add entry point ++ std::map 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 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::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::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::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 +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 +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 > & 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 +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 +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 +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 +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 +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 +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 > & 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 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 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::iterator j = r2r.find (i), k = j; +- j != r2r.end () && j->first == k->first;) ++ for (std::multimap::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::iterator j = r2r.find (regno), k = j; +- j != r2r.end () && j->first == k->first;) ++ for (std::multimap::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::iterator j = r2r.find (regno), k = j; +- j != r2r.end () && j->first == k->first;) ++ for (std::multimap::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 +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 +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 todo; ++ std::multimap 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 +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 +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 +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 +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 > & 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 fixups; ++ ++ // all paths to check ++ std::vector todo; ++ todo.push_back (index + 1); ++ ++ bool match_size = false; ++ bool ok = true; ++ std::set 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::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 +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 +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::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 +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 + #include + ++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 & 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 & 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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 positions; + std::vector > locs; + std::vector > 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::iterator i = positions.begin (); i != positions.end (); ++i) ++ printf ("%d ", *i); ++ printf ("\n"); ++ fflush (stdout); ++ } ++ + /* apply all changes. */ + for (std::vector >::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 +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 +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 +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 +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 & 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 +Date: Wed, 5 Jul 2017 20:20:50 +0200 +Subject: [PATCH 197/303] @B add ctype::~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::~ctype() ++ { ++ } ++ + char + ctype::do_toupper(char __c) const + { + +From f088c99da4c5cdb2b86c57475a2fddbb76deba6f Mon Sep 17 00:00:00 2001 +From: bebbo +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::~ctype() + { ++ _S_destroy_c_locale(_M_c_locale_ctype); ++ if (_M_del) ++ delete[] this->table(); + } ++#endif + + char + ctype::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::table_size; + ++#ifndef TARGET_AMIGA ++/* moved to ctype_configure_char */ + ctype::~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 +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 +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::~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::table_size; + +-#ifndef TARGET_AMIGA ++#ifndef __AMIGA__ + /* moved to ctype_configure_char */ + ctype::~ctype() + { + +From 8e243494b547e0452be69f9decc094f5cdf390db Mon Sep 17 00:00:00 2001 +From: bebbo +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 +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 +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 +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 +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 +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 +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 **)¤t) - 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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +-#include +-#include +- +-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::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::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 fixups; + +- if (ii.in_proepi ()) +- continue; ++ // all paths to check ++ std::vector 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 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 fixups; ++ for (; pos < infos.size (); ++pos) ++ { ++ insn_info & jj = infos[pos]; + +- // all paths to check +- std::vector 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 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::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::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 +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 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::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::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::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 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 +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 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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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") ) ++ (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") ) ++ (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 +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 +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 +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 +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::iterator k = fixups.begin (); k != fixups.end (); ++k) + +From 73e0e6c763bd79928606dece20538b1a65a53683 Mon Sep 17 00:00:00 2001 +From: fautomat +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 +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 +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 +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 +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 +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 +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 +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 +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 +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::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 +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 +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 +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 +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 ++#include ++#include + + 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 +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 +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 +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<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 +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; + +- 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<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 +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< +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) + 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<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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 > & 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 > & 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 positions; +- std::vector > locs; +- std::vector > patch; +- bool ok = true; +- +- for (std::set::iterator i = found.begin (); ok && i != found.end (); ++i) ++ for (std::set::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 >::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 >::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 +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 +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 +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 +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 +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 +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 +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 +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 +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<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 +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<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 +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 +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 +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(,<$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. -- cgit v1.2.3