From 8a8d2a77923f3e40a863272adeb828bccc8767c4 Mon Sep 17 00:00:00 2001 From: Chris Young Date: Sun, 21 Jan 2018 23:53:45 +0000 Subject: New approach Fork bebbo's version of gcc, add our changes and create a tarball from that. --- m68k-unknown-amigaos/Makefile | 8 +- m68k-unknown-amigaos/recipes/patches/gcc/gcc6.p | 11008 ---------------------- 2 files changed, 4 insertions(+), 11012 deletions(-) delete mode 100644 m68k-unknown-amigaos/recipes/patches/gcc/gcc6.p diff --git a/m68k-unknown-amigaos/Makefile b/m68k-unknown-amigaos/Makefile index 8a54b86..3174e9a 100644 --- a/m68k-unknown-amigaos/Makefile +++ b/m68k-unknown-amigaos/Makefile @@ -3,9 +3,9 @@ # sources -UPSTREAM_GCC_VERSION := 6.4.0 -UPSTREAM_GCC_TARBALL := gcc-$(UPSTREAM_GCC_VERSION).tar.xz -UPSTREAM_GCC_URI := http://ftp.gnu.org/gnu/gcc/gcc-$(UPSTREAM_GCC_VERSION)/$(UPSTREAM_GCC_TARBALL) +UPSTREAM_GCC_VERSION := 6.4.1b-20120122 +UPSTREAM_GCC_TARBALL := v$(UPSTREAM_GCC_VERSION).tar.gz +UPSTREAM_GCC_URI := https://github.com/chris-y/gcc/archive/$(UPSTREAM_GCC_TARBALL) UPSTREAM_BINUTILS_VERSION := 2.14 # Not a tarball; so sue me @@ -177,7 +177,7 @@ $(BUILDSTEPS)/srcdir-step2.d: $(BUILDSTEPS)/srcdir-step1.d $(SOURCESDIR)/$(UPSTR touch $@ $(BUILDSTEPS)/srcdir-step1.d: $(BUILDSTEPS)/$(UPSTREAM_GCC_TARBALL).d - tar xJf $(SOURCESDIR)/$(UPSTREAM_GCC_TARBALL) + tar xzf $(SOURCESDIR)/$(UPSTREAM_GCC_TARBALL) mv gcc-$(UPSTREAM_GCC_VERSION) $(GCC_SRCDIR) touch $@ diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc6.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc6.p deleted file mode 100644 index 25088ee..0000000 --- a/m68k-unknown-amigaos/recipes/patches/gcc/gcc6.p +++ /dev/null @@ -1,11008 +0,0 @@ -diff --git a/.cproject b/.cproject -new file mode 100755 -index 000000000000..6db4cbe2447e ---- /dev/null -+++ .cproject -@@ -0,0 +1,188 @@ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -diff --git a/.project b/.project -new file mode 100644 -index 000000000000..500c9ee08dca ---- /dev/null -+++ .project -@@ -0,0 +1,34 @@ -+ -+ -+ gcc-6 -+ -+ -+ -+ -+ -+ 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 -+ -+ -+ -+ 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 -new file mode 100755 -index 000000000000..caef162d88d1 ---- /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 -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/Makefile.in b/gcc/Makefile.in -index 51e2bc86e9a4..4aedf54bab12 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 \ -@@ -1986,7 +1987,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. -@@ -3270,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); \ -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/bbb-opts.c b/gcc/bbb-opts.c -new file mode 100755 -index 000000000000..9e989e9b1ec0 ---- /dev/null -+++ gcc/bbb-opts.c -@@ -0,0 +1,4705 @@ -+/* Bebbo's Optimizations. -+ Copyright (C) 2010-2017 Free Software Foundation, Inc. -+ Copyright (C) 2017 Stefan "Bebbo" Franke. -+ -+ 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 -+ * 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" -+#define INCLUDE_VECTOR -+#define INCLUDE_SET -+#define INCLUDE_MAP -+#include "system.h" -+#include "coretypes.h" -+#include "backend.h" -+#include "target.h" -+#include "rtl.h" -+#include "tm_p.h" -+#include "insn-config.h" -+#include "recog.h" -+#include "cfgrtl.h" -+#include "emit-rtl.h" -+#include "tree.h" -+#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; -+static char fxname[512]; -+static char const * -+get_current_function_name () -+{ -+ if (current_function_decl == NULL) -+ strcpy (fxname, ""); -+ else -+ strcpy (fxname, lang_hooks.decl_printable_name (current_function_decl, 2)); -+ return fxname; -+} -+ -+/* a simple log to stdout. */ -+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", get_current_function_name ()); -+ } -+ printf (":bbb: "); -+ int retval = vprintf (fmt, args); -+ va_end(args); -+ fflush (stdout); -+ return retval; -+} -+ -+enum proepis -+{ -+ IN_CODE, IN_PROLOGUE, IN_EPILOGUE, IN_EPILOGUE_PARALLEL_POP -+}; -+ -+/** -+ * What's needed to track values? -+ */ -+class track_var -+{ -+ 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)]; -+ unsigned mr = mask[REGNO(x)]; -+ /* try to expand the register. */ -+ if (v) -+ { -+ if (dstMode != GET_MODE(v) && (GET_CODE(v) != CONST_INT || mr == (1 << FIRST_PSEUDO_REGISTER))) -+ return false; -+ -+ *mask |= mr; -+ *z = v; -+ return true; -+ } -+ -+ /* store the reg otherwise. */ -+ *mask |= (1 << REGNO(x)); -+ if (GET_MODE(x) == dstMode) -+ *z = x; -+ else -+ *z = gen_rtx_REG (dstMode, REGNO(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; -+ } -+ default: -+ return false; -+ } -+ break; -+ } -+ default: -+ return false; -+ } -+ } -+ -+public: -+ track_var (track_var const * o = 0) -+ { -+ if (o) -+ assign (o); -+ else -+ for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i) -+ { -+ value[i] = 0; -+ mask[i] = 0; -+ } -+ } -+ -+ 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) -+ { -+ rtx z = 0; -+ unsigned m = 0; -+ if (extend (&z, &m, GET_MODE(dst), dst)) -+ { -+ for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i) -+ { -+ if (rtx_equal_p (z, value[i])) -+ { -+ value[i] = 0; -+ mask[i] = 0; -+ } -+ } -+ } -+ } -+ -+ rtx -+ get (unsigned regno) -+ { -+ if (regno >= FIRST_PSEUDO_REGISTER) -+ return 0; -+ -+ return value[regno]; -+ } -+ -+ void -+ set (machine_mode mode, unsigned regno, rtx x, unsigned index) -+ { -+ if (regno >= FIRST_PSEUDO_REGISTER) -+ return; -+ -+ if (mode == SFmode && regno < 16) -+ mode = SImode; -+ -+ if (!extend (&value[regno], &mask[regno], mode, x)) -+ { -+ clear (mode, regno, index); -+ } -+ } -+ -+ bool -+ equals (unsigned regno, rtx x) -+ { -+ if (regno >= FIRST_PSEUDO_REGISTER) -+ 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]); -+ } -+ -+ void -+ clear (machine_mode mode, unsigned regno, unsigned index) -+ { -+ if (regno >= FIRST_PSEUDO_REGISTER) -+ return; -+ -+ if (mode == SFmode && regno < 16) -+ mode = SImode; -+ value[regno] = gen_rtx_raw_CONST_INT(mode, 0x100000000000000LL | ((long long int ) (regno) << 32) | index); -+ mask[regno] = 1 << FIRST_PSEUDO_REGISTER; -+ } -+ -+ void -+ clear_aftercall (unsigned index) -+ { -+ for (int i = 2; i < FIRST_PSEUDO_REGISTER; ++i) -+ { -+ if (mask[i] && mask[i] < 1 << FIRST_PSEUDO_REGISTER) -+ { -+ value[i] = 0; -+ mask[i] = 0; -+ } -+ } -+ clear (SImode, 0, index); -+ clear (SImode, 1, index); -+ clear (SImode, 8, index); -+ clear (SImode, 9, index); -+ } -+ -+ void -+ clear_for_mask (unsigned def, unsigned index) -+ { -+ if (!def) -+ return; -+ for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) -+ { -+ // register changed or used somehow -+ if ((1 << regno) & def) -+ clear (SImode, 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. */ -+ void -+ merge (track_var * o, unsigned) -+ { -+ for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i) -+ { -+ if (!rtx_equal_p (value[i], o->value[i])) -+ { -+ value[i] = o->value[i] = 0; -+ mask[i] = 0; -+ } -+ } -+ } -+ -+ /* true if a merge would not change anything. */ -+ bool -+ no_merge_needed (track_var const * o) const -+ { -+ for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i) -+ { -+ if (!rtx_equal_p (value[i], o->value[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. -+ * -+ * Track use & def separate to determine starting points. -+ */ -+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 -+ -+ enum proepis proepi; -+ -+ bool stack; // part of stack frame insns -+ -+// stuff to analyze insns -+ bool label; -+ bool jump; -+ bool call; -+ bool compare; -+ bool dst_mem; -+ bool src_mem; -+ bool dst_plus; -+ bool src_plus; -+ rtx_code src_op; -+ bool src_ee; -+ bool src_2nd; -+ bool src_const; -+ -+ machine_mode mode; -+ -+ rtx dst_reg; -+ rtx dst_mem_reg; -+ rtx dst_symbol; -+ rtx src_reg; -+ rtx src_mem_reg; -+ rtx src_symbol; -+ unsigned dst_mem_addr; -+ int src_intval; -+ unsigned src_mem_addr; -+ -+ bool visited; -+ -+ int sp_offset; -+ -+ int dst_autoinc; -+ int src_autoinc; -+ -+// values for all variables - if used -+ track_var * track; -+ -+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_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), track (0) -+ { -+ } -+ -+ track_var * -+ get_track_var (); -+ -+ inline ptrdiff_t -+ operator < (insn_info const & o) const -+ { -+ return this - &o; -+ } -+ -+ int -+ get_index () const; -+ -+ void -+ plus_to_move (rtx_insn * newinsn); -+ -+ void -+ swap_adds (rtx_insn * newinsn, insn_info & ii); -+ -+ 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 -+ { -+ return compare; -+ } -+ -+ inline machine_mode -+ get_mode () const -+ { -+ return mode; -+ } -+ -+ inline bool -+ is_dst_reg () const -+ { -+ return dst_reg; -+ } -+ -+ inline bool -+ is_dst_mem () const -+ { -+ return dst_mem; -+ } -+ -+ inline bool -+ is_src_mem () const -+ { -+ return src_mem; -+ } -+ -+ inline bool -+ is_src_mem_2nd () const -+ { -+ return src_2nd && src_mem; -+ } -+ -+ inline bool -+ has_dst_memreg () const -+ { -+ 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 -+ { -+ return label; -+ } -+ -+ inline bool -+ is_jump () const -+ { -+ return jump; -+ } -+ -+ inline bool -+ is_call () const -+ { -+ return call; -+ } -+ -+ inline unsigned -+ get_dst_mem_addr () const -+ { -+ return dst_mem_addr; -+ } -+ -+ inline unsigned -+ get_src_mem_addr () const -+ { -+ return src_mem_addr; -+ } -+ -+ inline bool -+ is_src_reg () const -+ { -+ return src_reg && !src_op; -+ } -+ -+ inline int -+ get_src_op () const -+ { -+ return src_op; -+ } -+ -+ inline bool -+ is_src_ee () const -+ { -+ return src_ee; -+ } -+ -+ inline bool -+ is_src_mem_plus () const -+ { -+ return src_mem && src_plus; -+ } -+ -+ inline bool -+ is_dst_mem_plus () const -+ { -+ return dst_mem && dst_plus; -+ } -+ -+ inline int -+ get_dst_regno () const -+ { -+ return dst_reg ? REGNO(dst_reg) : -1; -+ } -+ -+ inline int -+ get_src_regno () const -+ { -+ return src_reg ? REGNO(src_reg) : -1; -+ } -+ -+ 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_dst_mem_regno () const -+ { -+ 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 -+ { -+ return src_intval; -+ } -+ -+ inline int -+ get_dst_intval () const -+ { -+ return dst_mem_addr; -+ } -+ -+ 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); -+ -+ void -+ fledder_src_mem (rtx src); -+ -+ /* 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 enum proepis -+ in_proepi () const -+ { -+ return proepi; -+ } -+ -+ inline void -+ set_proepi (enum proepis p) -+ { -+ proepi = p; -+ } -+ -+ inline void -+ reset_flags () -+ { -+ label = false; -+ jump = 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; -+ -+ 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 -+ is_empty () -+ { -+ return !def && !use && !hard; -+ } -+ -+ inline void -+ 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) -+ { -+ def |= 1 << regno; -+ } -+ -+ inline void -+ mark_hard (int regno) -+ { -+ hard |= 1 << regno; -+ } -+ -+ inline void -+ unset (int regno) -+ { -+ use &= ~(1 << regno); -+ def &= ~(1 << regno); -+ hard &= ~(1 << regno); -+ } -+ -+ inline unsigned -+ get_use () const -+ { -+ return use; -+ } -+ -+ inline unsigned -+ get_myuse () const -+ { -+ return myuse; -+ } -+ -+ inline void -+ set_use (unsigned u) -+ { -+ use = u; -+ } -+ -+ 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; -+ } -+ -+ inline bool -+ is_myuse (int regno) -+ { -+ return (myuse & (1 << regno)) != 0; -+ } -+ -+ inline bool -+ is_def (int regno) -+ { -+ return (def & (1 << regno)) != 0; -+ } -+ -+ inline bool -+ is_hard (int regno) -+ { -+ return (hard & (1 << regno)) != 0; -+ } -+ -+ inline void -+ clear_hard_def () -+ { -+ hard = 0; -+ def = 0; -+ } -+ -+ /* -+ * 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.def; -+ use |= o.use; -+ def = 0; -+ } -+ -+ inline insn_info & -+ merge (insn_info const & o) -+ { -+ myuse = o.myuse; -+ use = (use & ~o.def) | o.use; -+ def |= o.def; -+ hard |= o.hard; -+ 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 () -+ { -+ use &= ~def; -+ return *this; -+ } -+ -+ inline insn_info & -+ make_hard () -+ { -+ hard = use | def; -+ return *this; -+ } -+ -+ inline insn_info & -+ make_clobber () -+ { -+ hard = use = def = use | def; -+ return *this; -+ } -+ -+ inline bool -+ contains (insn_info const & o) const -+ { -+ if (o.def & ~def) -+ return false; -+ if (o.use & ~use) -+ return false; -+ if (o.hard & ~hard) -+ return false; -+ return true; -+ } -+ -+ inline int -+ get_sp_offset () const -+ { -+ return sp_offset; -+ } -+ -+ inline void -+ set_sp_offset (int sp) -+ { -+ sp_offset = sp; -+ } -+ -+ inline bool -+ is_visited () const -+ { -+ return visited; -+ } -+ -+ inline void -+ mark_visited () -+ { -+ visited = true; -+ } -+ -+ inline void -+ clear_visited () -+ { -+ visited = false; -+ } -+ -+ void -+ scan (); -+ -+ void -+ scan_rtx (rtx); -+ -+ bool -+ make_post_inc (int regno); -+ -+ void -+ auto_inc_fixup (int regno, int size); -+ -+ /* return bits for alternate free registers. */ -+ unsigned -+ get_free_mask () const -+ { -+ if (def & hard) -+ return 0; -+ -+ if (!def) -+ return 0; -+ -+ 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_no_cc > 0xff) -+ mask &= 0xff00; -+ -+ return mask & ~use; -+ } -+ -+ unsigned -+ get_regbit () const -+ { -+ if (GET_MODE_SIZE(mode) > 4) -+ return 0; -+ return def & ~hard & ~use & 0x7fff; -+ } -+ -+ void -+ set_insn (rtx_insn * newinsn); -+ -+ void -+ a5_to_a7 (rtx a7); -+}; -+ -+bool -+insn_info::make_post_inc (int regno) -+{ -+ rtx pattern = PATTERN (insn); -+ rtx_insn * new_insn = make_insn_raw (pattern); -+ -+ // convert into POST_INC -+ rtx set0 = single_set (new_insn); -+ if (!set0) -+ return false; -+ -+ rtx set = set0; -+ -+ 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) -+ { -+ if (src_op == NEG || src_op == NOT || src_op == SIGN_EXTEND) -+ mem = XEXP(mem, 0); -+ else -+ 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 (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; -+ 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 if (get_src_mem_regno () == regno) -+ { -+ // 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 (dst_mem_addr == (unsigned) size) -+ { -+ XEXP(mem, 0) = XEXP(plus, 0); -+ dst_mem_addr = 0; -+ dst_plus = false; -+ } -+ else -+ XEXP(plus, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(plus, 1)), dst_mem_addr -= size); -+ } -+ -+ rtx pattern = add_clobbers (insn); -+ -+ SET_INSN_DELETED(insn); -+ insn = emit_insn_after (pattern, insn); -+} -+ -+track_var * -+insn_info::get_track_var () -+{ -+ if (!track) -+ track = new track_var (); -+ return track; -+} -+ -+void -+insn_info::scan () -+{ -+ rtx pattern = PATTERN (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_myuse (0); -+ if (sz > 32) -+ { -+ mark_hard (1); -+ mark_myuse (1); -+ } -+ } -+ } -+ else if (CALL_P(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) -+ mark_myuse (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; -+ } -+ scan_rtx (pattern); -+} -+ -+/* scan rtx for registers and set the corresponding flags. */ -+void -+insn_info::scan_rtx (rtx x) -+{ -+ if (REG_P(x)) -+ { -+ for (int n = REG_NREGS(x), r = REGNO(x); n > 0; --n, ++r) -+ mark_myuse (r); -+ return; -+ } -+ -+ if (x == cc0_rtx) -+ { -+ mark_myuse (FIRST_PSEUDO_REGISTER); -+ return; -+ } -+ -+ RTX_CODE code = GET_CODE(x); -+ -+ /* handle SET and record use and def. */ -+ if (code == SET) -+ { -+ unsigned u = use; -+ unsigned mu = myuse; -+ use = myuse = 0; -+ 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; -+ } -+ -+ // 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; -+ 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--) -+ { -+ if (fmt[i] == 'e') -+ scan_rtx (XEXP(x, i)); -+ else if (fmt[i] == 'E') -+ for (int j = XVECLEN (x, i) - 1; j >= 0; j--) -+ { -+ unsigned u = use; -+ unsigned mu = myuse; -+ unsigned d = def; -+ scan_rtx (XVECEXP(x, i, j)); -+ use |= u; -+ myuse |= mu; -+ def |= d; -+ } -+ } -+ -+ if (code == POST_INC || code == PRE_DEC || code == CLOBBER) -+ def |= myuse; -+} -+ -+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) -+{ -+ if (!set || GET_CODE(set) == PARALLEL) -+ return; -+ -+ 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 (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); -+ -+ if (REG_P(dst)) -+ { -+ dst_reg = dst; -+ } -+ else if (MEM_P(dst)) -+ { -+ 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) -+ dst_mem_addr = INTVAL(mem); -+ else if (GET_CODE(mem) == SYMBOL_REF) -+ dst_symbol = 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 = reg; -+ 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)); -+ } -+ } -+ } -+ } -+ -+ /* 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') -+ { -+ src_ee = true; -+ rtx operand = XEXP(src, 1); -+ 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; -+ } -+ else if (MEM_P(operand)) -+ { -+ // it' something like reg = op(reg, mem(...)) -+ src_2nd = true; -+ fledder_src_mem (operand); -+ } -+ } -+ src = XEXP(src, 0); -+ } -+ -+ if (REG_P(src)) -+ { -+ src_reg = src; -+ } -+ else if (MEM_P(src)) -+ { -+ fledder_src_mem (src); -+ } -+ else if (GET_CODE(src) == CONST_INT) -+ { -+ src_const = true; -+ src_intval = INTVAL(src); -+ } -+ if (alt_src_reg) -+ src_reg = alt_src_reg; -+} -+ -+/* create a copy for a reg. Optional specify a new register number. */ -+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; -+} -+ -+/* Rename the register plus track all locs to undo these changes. */ -+static rtx -+find_reg_by_no (rtx x, unsigned oldregno) -+{ -+ if (!x) -+ return 0; -+ -+ 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) -+ return y; -+ } -+ else -+ { -+ 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); -+ rtx r = find_reg_by_no (z, oldregno); -+ if (r) -+ return r; -+ } -+ } -+ return 0; -+} -+ -+/* -+ * Collect some data. -+ */ -+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; -+ -+// 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 scan_starts; -+typedef std::set::iterator su_iterator; -+ -+static insn_info * info0; -+static unsigned usable_regs; -+ -+static void -+update_insn2index () -+{ -+ infos.reserve (infos.size () * 8 / 7 + 2); -+ 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]; -+ insn2info.insert (std::make_pair (ii.get_insn (), &ii)); -+ } -+ info0 = &infos[0]; -+} -+ -+static void -+update_label2jump () -+{ -+ update_insn2index (); -+ -+ for (unsigned index = 0; index < infos.size (); ++index) -+ { -+ insn_info & ii = infos[index]; -+ 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 -+{ -+ 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_op = (rtx_code) 0; -+ src_reg = XEXP(PATTERN (newinsn), 1); -+ insn2info.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); -+ -+ insn2info.insert (std::make_pair (insn, this)); -+ insn2info.insert (std::make_pair (ii.insn, &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) -+{ -+ 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); -+} -+ -+void -+insn_info::set_insn (rtx_insn * newinsn) -+{ -+ insn = newinsn; -+ -+ reset_flags (); -+ -+ fledder (single_set (insn)); -+} -+ -+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); -+ 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) -+ { -+ unsigned addr = get_dst_mem_addr (); -+ unsigned offset = addr - base; -+ if (offset <= 0x7ffe) -+ { -+ 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 (apply) -+ { -+ 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_mem_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))); -+ -+ /* 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 -+ { -+ 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); -+ } -+ } -+ -+ if (apply) -+ { -+ src_mem_reg = reg; -+ src_mem = true; -+ src_mem_addr = offset; -+ src_plus = offset != 0; -+ } -+ } -+ } -+ -+ 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); -+ -+ mark_myuse (regno); -+ -+ insn2info.insert (std::make_pair (insn, this)); -+} -+/* -+ * Reset collected data. -+ */ -+static void -+clear (void) -+{ -+ label2jump.clear (); -+ jump2label.clear (); -+ insn2info.clear (); -+ infos.clear (); -+ scan_starts.clear (); -+} -+ -+/* -+ * return true if the register is DEAD. -+ * Do not check at jumps. -+ */ -+static bool -+is_reg_dead (unsigned regno, unsigned _pos) -+{ -+// skip labels. -+ for (unsigned pos = _pos + 1; pos < infos.size (); ++pos) -+ { -+ insn_info & ii = infos[pos]; -+ // skip entries without info -+ if (ii.is_empty ()) -+ continue; -+ -+ // not dead if usage is reported in the next statement -+ return !ii.is_use (regno) && !ii.is_hard (regno); -+ } -+ 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; -+ -+ insn_info & ii = *i->second; -+ -+ if (f != stderr) -+ { -+ 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"); -+ } -+ -+ 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)) -+ { -+ fprintf (f, ii.is_hard (j) ? "!" : " "); -+ fprintf (f, ii.is_def (j) ? ii.is_use (j) ? "*" : "+" : ii.is_myuse (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) ? "*" : "+" : ii.is_myuse (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 "); -+ 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"); -+ -+} -+ -+/* -+ * Helper function to dump the code. -+ * Sometimes used during debugging. -+ */ -+static void -+dump_insns (char const * name, bool all) -+{ -+ fprintf (stderr, "====================================: %s\n", name); -+ if (all) -+ { -+ for (rtx_insn * insn = get_insns (); insn && insn != infos[0].get_insn (); insn = NEXT_INSN (insn)) -+ debug_rtx (insn); -+ } -+ 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, insn); -+ -+ fprintf (stderr, "\t"); -+ debug_rtx (insn); -+ -+ if (all) -+ { -+ 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); -+ } -+ } -+} -+ -+/* 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) -+{ -+ /* add all return (jump outs) and start analysis there. */ -+ std::set & todo = scan_starts; -+ -+ if (todo.begin () == todo.end ()) -+ todo.insert (infos.size () - 1); -+ -+ bool locka4 = flag_pic >= 3; -+ -+ while (!todo.empty ()) -+ { -+ int start = *todo.begin (); -+ todo.erase (todo.begin ()); -+ insn_info ii = infos[start]; -+ -+ 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]; -+ rtx_insn * insn = pp.get_insn (); -+ -+ // 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)) -+ break; -+ -+ ii.clear_hard_def (); -+ ii.merge (pp); -+ -+ if (LABEL_P(insn)) -+ { -+ /* work on all jumps referring to that label. */ -+ 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 (); -+ -+ /* 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; -+ } -+ -+ pp.mark_visited (); -+ -+ 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)) -+ { -+ if (pos != start && ii.in_proepi ()) -+ { -+ su_iterator k = scan_starts.find (pos); -+ if (k != scan_starts.end ()) -+ { -+ pp.clear_visited (); -+ break; -+ } -+ } -+ } -+ else if (GET_CODE (pattern) == USE || GET_CODE (pattern) == CLOBBER) -+ { -+ use.make_clobber (); -+ } -+ else if (single_set (insn) == 0) -+ use.make_hard (); -+ else -+ /* 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) -+ use.mark_def (FIRST_PSEUDO_REGISTER); -+ } -+ -+ // 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) -+ use.make_hard (); -+ -+ ii.merge (use); -+ pp.update (ii); -+ ii.updateWith (use); -+ } -+ } -+ -+ /* fill the mask of general used regs. */ -+ insn_info zz; -+ for (unsigned i = 0; i < infos.size (); ++i) -+ { -+ insn_info & ii = infos[i]; -+ if (ii.in_proepi () != IN_PROLOGUE) -+ 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); -+} -+ -+enum AbortCodes -+{ -+ E_OK, E_NO_JUMP_LABEL, E_JUMP_TABLE_MISMATCH, E_JUMP_GOTO_LABEL, E_SP_MISMATCH -+}; -+ -+/* -+ * Create a filtered view of insns - keep only those to work with. -+ */ -+static unsigned -+update_insns () -+{ -+ rtx_insn *insn, *next; -+ unsigned result = 0; -+ rtx jump_table = 0; -+ -+ clear (); -+ -+ enum proepis inproepilogue = IN_PROLOGUE; -+ /* 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)) -+ { -+ -+ infos.push_back (insn_info (insn, inproepilogue)); -+ insn_info & ii = infos[infos.size () - 1]; -+ -+ if (JUMP_P(insn)) -+ { -+ 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); -+ if (ANY_RETURN_P(PATTERN (insn)) -+ || (set && SET_DEST(set) == pc_rtx && GET_CODE(SET_SRC(set)) != IF_THEN_ELSE)) -+ continue; -+ } -+ -+ ii.mark_jump (); -+ if (jump_table) -+ { -+ if (XEXP(jump_table, 0) != insn) -+ { -+ if (be_very_verbose) -+ { -+ debug_rtx (insn); -+ debug_rtx (jump_table); -+ } -+ result = E_JUMP_TABLE_MISMATCH; -+ jump_table = 0; -+ continue; -+ } -+ -+ // -> jump_table_data -+ rtx table = PATTERN (XEXP(jump_table, 1)); -+ if (GET_CODE(table) == ADDR_DIFF_VEC || GET_CODE(table) == ADDR_VEC) -+ { -+ 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)); -+ ii.set_proepi (IN_EPILOGUE); -+ } -+ } -+ } -+ else -+ { -+ if (be_very_verbose) -+ { -+ 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; -+ ii.set_proepi (inproepilogue = IN_CODE); -+ if (infos.size () > 1) -+ 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); -+ } -+ ii.mark_call (); -+ if (inproepilogue) -+ { -+ scan_starts.insert (infos.size () - 1); -+ inproepilogue = IN_CODE; -+ } -+ } -+ else -+ { -+ 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); -+ } -+ } -+ -+ } -+ } -+ else if (NOTE_P(insn)) -+ { -+ if (NOTE_KIND(insn) == NOTE_INSN_PROLOGUE_END) -+ inproepilogue = IN_CODE; -+ else if (NOTE_KIND(insn) == NOTE_INSN_EPILOGUE_BEG) -+ inproepilogue = IN_EPILOGUE; -+ } -+ } -+ scan_starts.insert (infos.size () - 1); -+ update_insn2index (); -+ update_insn_infos (); -+ -+ return result; -+} -+ -+/* convert the lowest set bit into a register number. */ -+static int -+bit2regno (unsigned bit) -+{ -+ if (!bit) -+ return -1; -+ -+ unsigned regno = 0; -+ while (!(bit & 1)) -+ { -+ ++regno; -+ bit >>= 1; -+ } -+ 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 = infos[index]; -+ if (ii.is_myuse (regno) || ii.is_def (regno)) -+ return true; -+ } -+ return false; -+} -+ -+/* -+ * search backward and find the initial assignment for that regno. -+ */ -+static unsigned -+find_start (unsigned start, unsigned rename_regno) -+{ -+ /* search the start. */ -+ while (start > 0) -+ { -+ unsigned startm1 = start - 1; -+ -+ /* 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; -+ -+ /* found the definition without use. */ -+ if (jj.is_def (rename_regno) && !jj.is_use (rename_regno)) -+ break; -+ -+ start = startm1; -+ } -+ return start; -+} -+ -+/* -+ * Always prefer lower register numbers within the class. -+ */ -+static unsigned -+opt_reg_rename (void) -+{ -+ update_label2jump (); -+// dump_insns ("rename", 1); -+ for (unsigned index = 0; index < infos.size (); ++index) -+ { -+ insn_info & ii = infos[index]; -+ -+ /* do not rename if register is hard or used in same statement. */ -+ const unsigned rename_regbit = ii.get_regbit (); -+ if (!rename_regbit) -+ continue; -+ -+ const unsigned rename_regno = bit2regno (rename_regbit); -+ -+ /* 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); -+ -+ if (!mask) -+ continue; -+ -+ /* first = pos to start, second indicates to treat def as use. */ -+ std::set todo; -+ std::set found; -+ if (index + 1 < infos.size ()) -+ todo.insert (index + 1); -+ -+ found.insert (index); -+ /* a register was defined, follow all branches. */ -+ while (mask && todo.begin () != todo.end ()) -+ { -+ 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. */ -+ if (found.find (pos) != found.end ()) -+ break; -+ -+ rtx_insn * insn = infos[pos].get_insn (); -+ 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 (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 ()) -+ { -+ mask = 0; -+ break; -+ } -+ -+ unsigned startat = j->second->get_index (); -+ 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); -+ } -+ -+ /* 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 > 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; -+ -+// 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 (pos - 1, rename_regno); -+ todo.insert (start); -+// printf ("label %d : start %d \n", pos, start); fflush (stdout); -+ } -+ } -+ -+ continue; -+ } -+ -+ insn_info & jj = infos[pos]; -+ -+ /* marked as hard reg -> invalid rename */ -+ if (jj.get_use () & jj.get_hard () & rename_regbit) -+ { -+ mask = 0; -+ break; -+ } -+ -+ /* not used. and not a def */ -+ if (pos == runpos && (jj.get_def () & rename_regbit)) -+ { -+ /* continue since this pos was added by start search. */ -+ } -+ 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 (); -+ if (!mask) -+ break; -+ -+ found.insert (pos); -+ -+ /* follow jump and/or next insn. */ -+ if (JUMP_P(insn)) -+ { -+ for (j2l_iterator i = jump2label.find (pos), k = i; i != jump2label.end () && i->first == k->first; -+ ++i) -+ { -+ unsigned label_index = i->second; -+ -+ /* add the label to the search list. */ -+ insn_info & bb = infos[label_index + 1]; -+ if (found.find (label_index) == found.end () && bb.is_use (rename_regno)) -+ { -+// printf ("jump %d -> label %d \n", pos, label_index); fflush (stdout); -+ todo.insert (label_index); -+ } -+ } -+ rtx set = single_set (insn); -+ 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; -+ } -+ } -+ } -+ -+ if (mask) -+ { -+ int oldregno = bit2regno (rename_regbit); -+ int newregno = bit2regno (mask); -+ -+ /* check the renamed insns. */ -+ std::vector positions; -+ for (std::set::iterator i = found.begin (); i != found.end (); ++i) -+ { -+ insn_info & rr = infos[*i]; -+ rtx_insn * insn = rr.get_insn (); -+ -+ /* get rename locations. */ -+ 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); -+ -+ positions.push_back (*i); -+ } -+ } -+ -+ if (!apply_change_group ()) -+ continue; -+ -+ log ("(r) opt_reg_rename %s -> %s (%d locs, start at %d)\n", reg_names[oldregno], reg_names[newregno], -+ positions.size (), index); -+ -+ if (be_verbose) -+ { -+ for (std::vector::iterator i = positions.begin (); i != positions.end (); ++i) -+ printf ("%d ", *i); -+ printf ("\n"); -+ fflush (stdout); -+ } -+ -+ return 1; -+ } -+ } -+ return 0; -+} -+ -+/* -+ * #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 -+ -+ * -+ * 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 unsigned -+opt_propagate_moves () -+{ -+ unsigned change_count = 0; -+ rtx_insn * current_label = 0; -+ unsigned current_label_index; -+ std::vector reg_reg; -+ std::vector jump_out; -+ -+ /* start at 1 since there must be an insn before the label. */ -+ for (unsigned index = 1; index < infos.size (); ++index) -+ { -+ rtx_insn * insn = infos[index].get_insn (); -+ -+ 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; -+ } -+ -+ 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 (index); -+ } -+ else -+ current_label = 0; -+ -+ continue; -+ } -+ -+ if (JUMP_P(insn)) -+ { -+ 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 (); -+ ) -+ { -+ bool inc = true; -+ for (std::vector::iterator j = i + 1; j != reg_reg.end ();) -+ { -+ 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 = infos[*j].get_insn (); -+ 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 (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::iterator label_iter = jump_out.begin (); -+ int fixup = 0; -+ -+ for (unsigned k = *i + 1; k != *j; ++k) -+ { -+ rtx_insn * check = infos[k].get_insn (); -+ 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 = infos[current_label_index - 1].get_insn (); -+ rtx_insn * after = infos[index + 1].get_insn (); -+ rtx bset = single_set (before); -+ -+ log ("(p) 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); -+ -+ /* Plus check if the reg was just loaded. */ -+ if (bset) -+ { -+ rtx bdst = SET_DEST(bset); -+ if (REG_P(bdst) && REGNO(bdst) == REGNO(srci)) -+ { -+ 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. */ -+ 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; -+ -+ /* add fixes if there were jumps out of the loop. */ -+ if (jump_out.size ()) -+ { -+ log ("(p) 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]))); -+ emit_insn_after (neu, jump_out[k]); -+ } -+ } -+ ++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 unsigned -+opt_strcpy () -+{ -+ unsigned change_count = 0; -+#if HAVE_cc0 -+ rtx_insn * x2reg = 0; -+ rtx_insn * reg2x; -+ unsigned int regno; -+ -+ for (unsigned index = 0; index < infos.size (); ++index) -+ { -+ rtx_insn * insn = infos[index].get_insn (); -+ -+ if (!NONJUMP_INSN_P(insn)) -+ { -+ x2reg = 0; -+ continue; -+ } -+ -+ rtx set = single_set (insn); -+ if (!set) -+ { -+ x2reg = 0; -+ continue; -+ } -+ -+ if (x2reg && reg2x) -+ { -+ rtx 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)) -+ 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); -+ if (cc_status.flags == 0 && rtx_equal_p (dst, cc_status.value2)) -+ { -+ rtx pattern = gen_rtx_SET(SET_DEST(single_set (reg2x)), SET_SRC(single_set (x2reg))); -+ rtx_insn * newinsn = make_insn_raw (pattern); -+ -+ 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)]); -+ -+ 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; -+ } -+ } -+ } -+ 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)); -+ } -+ } -+ } -+#endif -+ return change_count; -+} -+ -+/* -+ * 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 -+opt_commute_add_move (void) -+{ -+ unsigned change_count = 0; -+ -+ 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 ()) -+ 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 ()) -+ continue; -+ -+ rtx_insn * insn = ii.get_insn (); -+ -+ rtx_insn * next = jj.get_insn (); -+ rtx set2 = single_set (next); -+ rtx dst = SET_DEST(set2); -+ if (!MEM_P(dst)) -+ continue; -+ -+ 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 ())); -+ -+ 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 (newinsn, next); -+ -+ add_reg_note (next, REG_INC, ii.get_dst_reg ()); -+ -+ ++change_count; -+ } -+ else -+ cancel_changes (0); -+ } -+ 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 -+opt_const_cmp_to_sub (void) -+{ -+ unsigned change_count = 0; -+#if HAVE_cc0 -+ if (infos.size () < 2) -+ return change_count; -+ -+ unsigned lastsub = 0; -+ for (unsigned index = infos.size () - 2; index > 0; --index) -+ { -+ insn_info & i1 = infos[index]; -+ -+ /* we wan't a compare or tst insn, */ -+ if (!i1.is_compare ()) -+ continue; -+ -+ if (GET_MODE_SIZE(i1.get_mode()) > 4 || !i1.is_dst_reg () || REGNO(i1.get_dst_reg()) > 7) -+ continue; -+ -+ /* src must be a reg dead register with a constant - or a #0 */ -+ 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. */ -+ 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 (); -+ -+ // 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; -+ -+ 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 (GET_MODE_SIZE(i0.get_mode()) > 4) -+ continue; -+ -+ if (!i0.is_dst_reg () || !i0.is_src_const () || i0.get_src_op ()) -+ continue; -+ -+ if (i0.get_dst_regno () != i1.get_src_regno ()) -+ continue; -+ -+ intval = -i0.get_src_intval (); -+ if (intval < -8 || intval > 7) -+ continue; -+ -+ /* is the next sub value in range? */ -+ if (lastsub == index + 3 && (lastsubval - intval < -8 || lastsubval - intval > 7)) -+ continue; -+ } -+ -+ /* next insn must be the jump. */ -+ insn_info & i2 = infos[index + 1]; -+ if (!i2.is_jump ()) -+ continue; -+ -+ rtx jmppattern = single_set (i2.get_insn ()); -+ if (!jmppattern) -+ continue; -+ -+ rtx jmpsrc = XEXP(jmppattern, 1); -+ if (GET_CODE(jmpsrc) != IF_THEN_ELSE) -+ continue; -+ -+ rtx condition = XEXP(jmpsrc, 0); -+ RTX_CODE code = GET_CODE(condition); -+ if (code != EQ && code != NE) -+ continue; -+ -+ if (intval) -+ { -+ 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_insn * subinsn = make_insn_raw (gen_rtx_SET(copyreg, sub)); -+ -+ if (insn_invalid_p (subinsn, 0)) -+ continue; -+ -+ /* 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() */ -+ -+ /* convert cmp/tst into sub */ -+ 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))); -+ -+ emit_insn_before (neu, i2.get_insn ()); -+ -+ 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 ()]); -+ -+ 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 (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 -+ { -+ /* modify the sub. */ -+ XEXP(SET_SRC(PATTERN(pp.get_insn())), 1) = c; -+ } -+ } -+ -+ lastsub = index; -+ ++change_count; -+ } -+ } -+#endif -+ 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 -+opt_merge_add (void) -+{ -+ unsigned change_count = 0; -+ for (unsigned index = 0; index + 2 < infos.size (); ++index) -+ { -+ insn_info & ii0 = infos[index]; -+ insn_info & ii1 = infos[index + 1]; -+ insn_info & ii2 = infos[index + 2]; -+ -+ if (!ii2.is_dst_reg ()) -+ { -+ index += 2; -+ continue; -+ } -+ -+ if (!ii1.is_dst_reg ()) -+ { -+ ++index; -+ continue; -+ } -+ -+ 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 ()) -+ continue; -+ -+ if (ii0.get_dst_regno () != ii1.get_dst_regno () || ii1.get_src_regno () != ii2.get_dst_regno ()) -+ continue; -+ -+ rtx_insn * insn1 = ii1.get_insn (); -+ -+ CC_STATUS_INIT; -+ NOTICE_UPDATE_CC(PATTERN (insn1), insn1); -+ if (cc_status.value1 || cc_status.value2) -+ continue; -+ -+ log ("(m) %d: merge_add applied\n", index); -+ -+ rtx_insn * insn0 = ii0.get_insn (); -+ 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))); -+ add_insn_after (newins0, insn0, 0); -+ SET_INSN_DELETED(insn0); -+ // update infos accordingly -+ ii0.plus_to_move (newins0); -+ -+ 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); -+ -+ ++change_count; -+ } -+ return change_count; -+} -+ -+/* Update the insn_infos to 'know' the sp offset. */ -+static unsigned -+track_sp () -+{ -+// 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 -+ std::set todo; -+ todo.insert (0); -+ -+ while (todo.begin () != todo.end ()) -+ { -+ unsigned startpos = *todo.begin (); -+ todo.erase (todo.begin ()); -+ -+ 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 () != IN_CODE) -+ { -+ ii.set_sp_offset (sp_offset); -+ 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.insert (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.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 (); -+ 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; -+} -+ -+/* 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 -+ * 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 -+opt_shrink_stack_frame (void) -+{ -+ /* nothing to do. */ -+ 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; -+ rtx_insn * insn = infos[pos].get_insn (); -+ if (JUMP_P(insn)) /* return -> empty function*/ -+ return 0; -+ -+ bool usea5 = false; -+ int paramstart = 4; -+ int a5offset = 0; -+ -+ /* -+ * Move prologue to temp. -+ * Only register push and parallel insn unless its a link a5 are moved. -+ */ -+ for (; pos < infos.size ();) -+ { -+ insn_info & ii = infos[pos]; -+ insn = ii.get_insn (); -+ -+ if (ii.in_proepi () != IN_PROLOGUE) -+ break; -+ -+ rtx pattern = PATTERN (insn); -+ if (GET_CODE(pattern) == PARALLEL) -+ { -+ 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) -+ { -+ a5pos.push_back (pos); -+ usea5 = true; -+ set = XVECEXP(pattern, 0, 2); -+ a5offset = INTVAL(XEXP(SET_SRC(set), 1)); -+ } -+ ++pos; -+ continue; -+ } -+ 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; -+ } -+ -+ /* 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) == STACK_POINTER_REGNUM) -+ { -+ ii.mark_stack (); -+ } -+ } -+ } -+ } -+ 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) == STACK_POINTER_REGNUM && CONST_INT_P(cx)) -+ paramstart -= INTVAL(cx); -+ } -+ -+ if (++pos >= infos.size ()) -+ { -+ return 0; -+ } -+ } -+ -+ if (pos == 0) -+ return 0; -+ -+ unsigned prologueend = pos; -+ -+ /* search epilogues - there can be multiple epilogues. */ -+ while (pos < infos.size ()) -+ { -+ while (pos < infos.size ()) -+ { -+ if (infos[pos].in_proepi () != IN_CODE) -+ break; -+ ++pos; -+ } -+ -+ /* move epilogues away. */ -+ for (; pos < infos.size (); ++pos) -+ { -+ insn_info & ii = infos[pos]; -+ insn = ii.get_insn (); -+ if (JUMP_P(insn) || LABEL_P(insn) || ii.in_proepi () == IN_CODE) -+ break; -+ -+ /* omit the frame pointer a5. */ -+ rtx pattern = PATTERN (insn); -+ if (GET_CODE(pattern) == PARALLEL) -+ { -+ 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) -+ { -+ a5pos.push_back (pos); -+ break; -+ } -+ -+ } -+ 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) == 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 (); -+ } -+ } -+ } -+ } -+ } -+ ++pos; -+ } -+ /* gather usage stats without prologue/epilogue */ -+ insn_info ii; -+ for (unsigned i = 0; i < infos.size (); ++i) -+ { -+ insn_info & jj = infos[i]; -+ if (jj.in_proepi () != IN_CODE) -+ continue; -+ -+ ii.or_use (jj); -+ } -+ 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; -+ 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) -+ { -+ 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) -+ { -+ // 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; -+ -+ 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) -+ { -+ rtx set = XVECEXP(pattern, 0, j); -+ if (GET_CODE(set) == CLOBBER) -+ { -+ clobbers.push_back (set); -+ continue; -+ } -+ rtx dst = SET_DEST(set); -+ rtx src = SET_SRC(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); -+ -+ ++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 += GET_MODE_SIZE(GET_MODE(reg)); -+ } -+ else -+ { -+ regs_total_size += GET_MODE_SIZE(GET_MODE(reg)); -+ regs.push_back (copy_reg (reg, -1)); -+ } -+ } -+ -+ /* 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 (regs.size () < regs_seen) -+ { -+ log ("(f) shrinking stack frame from %d to %d\n", regs_seen, regs.size ()); -+ if (regs.size () <= 2) -+ { -+ changed = 1; -+ for (unsigned k = 0; k < regs.size (); ++k) -+ { -+ rtx reg = regs[k]; -+ if (i < prologueend) -+ { -+ /* push */ -+ 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(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); -+ } -+ } -+ } -+ else -+ { -+ rtx parallel = gen_rtx_PARALLEL(VOIDmode, rtvec_alloc (regs.size () + add1 + clobbers.size ())); -+ rtx plus; -+ -+ int x = 0; -+ 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 (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); -+ ++l; -+ } -+ -+ if (i >= prologueend) -+ x = usea5 ? -x : 0; -+ -+ for (unsigned k = 0; k < regs.size (); ++k, ++l) -+ { -+ if (i < prologueend) -+ { -+ /* push */ -+ 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]); -+ XVECEXP(parallel, 0, l) = set; -+ } -+ else -+ { -+ /* pop */ -+ 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, l) = 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, l) = set; -+ } -+ } -+ } -+ -+ for (unsigned k = 0; k < clobbers.size (); ++k, ++l) -+ { -+ rtx clobber = clobbers[k]; -+ XVECEXP(parallel, 0, l) = clobber; -+ } -+ -+ 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; -+ } -+ } -+ else -+ { -+ rtx set = PATTERN (insn); -+ -+ if (i < prologueend) -+ { -+ /* move x,-(a7). */ -+ rtx src = SET_SRC(set); -+ paramstart += REGNO(src) > STACK_POINTER_REGNUM ? 12 : 4; -+ unsigned regbit = 1 << REGNO(src); -+ if (freemask & regbit) -+ { -+ adjust += REGNO(src) > STACK_POINTER_REGNUM ? 12 : 4; -+ log ("(f) remove push for %s\n", reg_names[REGNO(src)]); -+ SET_INSN_DELETED(insn); -+ ++changed; -+ } -+ } -+ else -+ { -+ /* move (a7)+,x */ -+ rtx dst = SET_DEST(set); -+ unsigned regbit = 1 << REGNO(dst); -+ if (freemask & regbit) -+ { -+ log ("(f) remove pop for %s\n", reg_names[REGNO(dst)]); -+ SET_INSN_DELETED(insn); -+ ++changed; -+ } -+ } -+ } -+ } -+ -+ /* fix sp offsets. */ -+ if (!usea5 && adjust) -+ { -+ for (unsigned index = 0; index < infos.size (); ++index) -+ { -+ insn_info & ii = infos[index]; -+ if (ii.in_proepi () != IN_CODE) -+ continue; -+ -+ rtx pattern = single_set (ii.get_insn ()); -+ if (pattern) -+ patch_sp (pattern, adjust, ii.get_sp_offset ()); -+ } -+ } -+ -+ 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 ("(f) dropping unused frame pointer\n"); -+ for (std::vector::reverse_iterator i = a5pos.rbegin (); i != a5pos.rend (); ++i) -+ { -+ int index = *i; -+ SET_INSN_DELETED(infos[index].get_insn ()); -+ -+ // 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 () >= 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 ()))); -+ emit_insn_before (pattern, ii.get_insn ()); -+ } -+ } -+ -+ /* 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 (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); -+ } -+ -+ update_insn2index (); -+ ++changed; -+ } -+ } -+ -+ return changed; -+} -+ -+/* Update the insn_infos to 'know' the value for each register. -+ * -+ * assignments to registers are optimized by knowing the value. If the same value is assigned, omit that insn. -+ * -+ * I'm tracking -+ * -+ * rtx - the value -+ * -+ * 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 -+ * -+ * e.g. -+ * -+ * ; line 2 -+ * move.l 12(a7),a0 -+ * -+ * -> rtx = mem(plus(a7, 12)); 0x8000 -+ * -+ * ; line 10 -+ * move.l 4(a0),d0 -+ * -+ * -> rtx = mem(plus(mem(plus(a7, 12)), 4)); 0x8000; extended with value from a0, thus a7 is used only -+ * -+ * ;15 -+ * lea _label,a1 -+ * -+ * -> 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 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 setting a register is evaluated against the track info. -+ * -+ * now redundant loads are found and eliminated -+ * -+ */ -+ -+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); -+ } -+ -+ update_label2jump (); -+ -+// add entry point -+ std::multimap todo; -+ todo.insert (std::make_pair (0, new track_var ())); -+ -+ while (todo.begin () != todo.end ()) -+ { -+ unsigned startpos = todo.begin ()->first; -+ 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)) -+ break; -+ -+ // only keep common values at labels -+ if (ii.is_label ()) -+ { -+ if (ii.is_visited ()) -+ { -+ ii.get_track_var ()->merge (track, index); -+ } -+ else -+ { -+ ii.get_track_var ()->assign (track); -+ ii.mark_visited (); -+ } -+ continue; -+ } -+ -+ // mark current insn_info and set sp_offset -+ ii.mark_visited (); -+ ii.get_track_var ()->assign (track); -+ -+ if (ii.is_compare ()) -+ continue; -+ -+ unsigned def = ii.get_def () & 0xffffff; -+ 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 ()) -+ { -+ track->clear_aftercall (index); -+ 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) -+ continue; -+ -+ // unconditional jump -+ break; -+ } -+ -+ if (!set || !ii.get_def ()) -+ continue; -+ -+ if (dregno < 0) -+ { -+ 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 ())) -+ continue; -+ -+ rtx src = SET_SRC(set); -+ if (ii.is_src_mem () && src->volatil) -+ continue; -+ -+ track->set (ii.get_mode (), dregno, src, index); -+ } -+ delete track; -+ } -+ 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 (int blocked_regno) -+{ -+ track_regs (); -+ -+ unsigned change_count = 0; -+ for (int index = infos.size () - 1; index >= 0; --index) -+ { -+ insn_info & ii = infos[index]; -+ 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_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); -+ ++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_myuse (ii.get_dst_regno ()) || ii.get_dst_regno () == ii.get_src_regno ())) -+ { -+ track_var * track = ii.get_track_var (); -+ -+ rtx src = SET_SRC(set); -+ if (track->equals (ii.get_dst_regno (), src)) -+ { -+ log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]); -+ SET_INSN_DELETED(insn); -+ ++change_count; -+ continue; -+ } -+ -+ if (ii.get_src_reg () && track->equals (ii.get_src_regno (), SET_DEST(set))) -+ { -+ log ("(e) %d: eliminate redundant reverse load to %s\n", index, reg_names[ii.get_dst_regno ()]); -+ SET_INSN_DELETED(insn); -+ ++change_count; -+ continue; -+ } -+ -+ // is there a register holding that value? -+ if (!ii.get_src_reg ()) -+ { -+ int aliasRegno = track->find_alias (src); -+ if (aliasRegno >= 0 && aliasRegno != ii.get_dst_regno ()) -+ { -+ log ("(e) %d: replace load with %s\n", index, reg_names[aliasRegno]); -+ validate_change (ii.get_insn (), &SET_SRC(set), gen_rtx_REG (ii.get_mode (), aliasRegno), 0); -+ ++change_count; -+ } -+ } -+ } -+ } -+ return change_count; -+} -+ -+/* -+ * Convert a series of move into absolute address into register based moves. -+ */ -+static unsigned -+opt_absolute (void) -+{ -+ unsigned change_count = 0; -+ -+ for (unsigned i = 0; i < infos.size (); ++i) -+ { -+ insn_info & ii = infos[i]; -+ -+ 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 (); -+ -+ 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; -+ -+ rtx with_symbol = is_dst ? ii.get_dst_symbol () : ii.get_src_symbol (); -+ -+ std::vector found; -+ found.push_back (i); -+ int base = ii.get_dst_mem_addr (); -+ int max = base; -+ unsigned j = i + 1; -+ for (; j < infos.size (); ++j) -+ { -+ insn_info & jj = infos[j]; -+ /* 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; -+ -+ unsigned tempmask = freemask & ~(jj.get_use () | jj.get_def ()); -+ if (!tempmask) -+ break; -+ freemask = tempmask; -+ -+ 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 () -+ && jj.get_src_symbol () == with_symbol; -+ -+ /* exclude operations on that symbol. */ -+ -+ if (j_dst) -+ { -+ int addr = jj.get_dst_mem_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; -+ } -+ } -+ if (j_src) -+ { -+ int addr = jj.get_src_mem_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; -+ } -+ } -+ } -+ -+ if (freemask && found.size () > 2) -+ { -+ unsigned regno = bit2regno (freemask); -+ /* check again. */ -+ for (std::vector::iterator k = found.begin (); k != found.end ();) -+ { -+ insn_info & kk = infos[*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_mem_addr () - base > 0x7ffc) -+ 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; -+ } -+ } -+ if (freemask && found.size () > 2) -+ { -+ unsigned regno = bit2regno (freemask); -+ if (with_symbol) -+ 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]); -+ -+ unsigned current_use = ii.get_use (); -+ -+ for (std::vector::iterator k = found.begin (); k != found.end (); ++k) -+ { -+ insn_info & kk = infos[*k]; -+ kk.absolute2base (regno, base, with_symbol); -+ insn_invalid_p (kk.get_insn (), 0); -+ } -+ -+ // load base into reg -+ 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 (current_use); -+ nn.scan (); -+ nn.fledder (lea); -+ nn.mark_def (regno); -+ infos.insert (infos.begin () + i, nn); -+ -+ /* 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; -+ } -+ } -+ -+ if (change_count) -+ update_insn2index (); -+ -+ return change_count; -+} -+ -+static int -+try_auto_inc (unsigned index, insn_info & ii, rtx reg) -+{ -+ int const regno = REGNO(reg); -+ unsigned size = GET_MODE_SIZE(ii.get_mode ()); -+ if (size > 4) -+ return 0; -+ -+// 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; -+ std::set visited; -+ while (todo.size () > 0) -+ { -+ unsigned pos = todo[todo.size () - 1]; -+ todo.pop_back (); -+ -+ if (pos == index) -+ return 0; -+ -+ if (visited.find (pos) != visited.end ()) -+ continue; -+ visited.insert (pos); -+ -+ for (; pos < infos.size (); ++pos) -+ { -+ insn_info & jj = infos[pos]; -+ -+ // 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)) -+ return 0; -+ } -+ break; -+ } -+ -+ // break if no longer used -+ if (!jj.is_use (regno)) -+ break; -+ -+ if (jj.in_proepi ()) -+ return 0; -+ -+ // 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; -+ -+ // can't fixup such kind of insn (yet) -+ 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) -+ { -+ if (jj.get_dst_regno () == regno) -+ return 0; -+ -+ if (jj.get_src_mem_addr () < size) -+ return 0; -+ -+ if (jj.get_src_mem_addr () == size) -+ match_size = true; -+ -+ fix = true; -+ } -+ if (jj.get_dst_mem_regno () == regno) -+ { -+ if (jj.get_src_regno () == regno) -+ return 0; -+ -+ if (jj.get_dst_mem_addr () < size) -+ return 0; -+ -+ if (jj.get_dst_mem_addr () == size) -+ match_size = true; -+ -+ fix = true; -+ } -+ -+ if (!fix) -+ return 0; -+ -+ fixups.insert (pos); -+ -+ // done if this is an add -+ if (ii.is_def (regno)) -+ break; -+ } -+ } -+ -+ if (!match_size || !fixups.size ()) -+ return 0; -+ -+ 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 ()); -+ -+ // 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; -+} -+ -+/* -+ * 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 (!INSN_P(ii.get_insn ())) -+ continue; -+ -+// // more than one reg used -+// if (ii.get_myuse () & (ii.get_myuse () - 1)) -+// continue; -+ -+// // don't if fp regs are touched -+// if ((ii.get_myuse () & 0xff0000)) -+// continue; -+ -+ 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 (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 ()); -+ -+ } -+ -+ return change_count; -+} -+ -+namespace -+{ -+ -+ const pass_data pass_data_bbb_optimizations = -+ { RTL_PASS, /* type */ -+ "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 */ -+ 0, //( 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), pp (0) -+ { -+ } -+ -+ /* opt_pass methods: */ -+ virtual bool -+ gate (function *) -+ { -+ if (!string_bbb_opts) -+ string_bbb_opts = "+"; -+ -+ return TARGET_AMIGA && optimize > 0 && string_bbb_opts && !strchr (string_bbb_opts, '-'); -+ } -+ -+ virtual unsigned int -+ execute (function *) -+ { -+ return execute_bbb_optimizations (); -+ } -+ -+ opt_pass * -+ clone () -+ { -+ 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 -+ -+ /* Main entry point to the pass. */ -+ 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) -+ ++be_very_verbose; -+ if (be_very_verbose) -+ be_verbose = true; -+ -+ bool do_commute_add_move = strchr (string_bbb_opts, 'a') || 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_elim_dead_assign = strchr (string_bbb_opts, 'e') || strchr (string_bbb_opts, '+'); -+ bool do_shrink_stack_frame = strchr (string_bbb_opts, 'f') || 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"); -+ -+ unsigned r = update_insns (); -+ if (!r) -+ { -+ for (;;) -+ { -+ 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_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_merge_add && opt_merge_add ()) -+ done = 0; -+ -+ if (do_elim_dead_assign && opt_elim_dead_assign (STACK_POINTER_REGNUM)) -+ done = 0, update_insns (); -+ -+ if (do_absolute && opt_absolute ()) -+ done = 0, update_insns (); -+ -+ if (do_autoinc && opt_autoinc ()) -+ done = 0, update_insns (); -+ -+ if (do_bb_reg_rename) -+ { -+ while (opt_reg_rename ()) -+ { -+ update_insns (); -+ done = 0; -+ } -+ } -+ -+ if (done) -+ break; -+ } -+ -+ if (do_shrink_stack_frame) -+ { -+ 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); -+ -+ 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; -+ } -+ -+} // anon namespace -+ -+rtl_opt_pass * -+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) -+ ispicref = amiga_is_const_pic_ref (XEXP(*src, 0)); -+ else -+ ispicref = amiga_is_const_pic_ref (*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/c/c-decl.c b/gcc/c/c-decl.c -index e8bafedd7357..642829b828c7 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 -@@ -4439,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 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], NULL); -+ } -+ 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; - } - - -@@ -5024,6 +5051,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 +5091,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 fc20bad8d992..91cfc2c5e193 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 -@@ -3892,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 -@@ -3903,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/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/cfgcleanup.c b/gcc/cfgcleanup.c -index 6e92d4cdde22..378b1fc595bb 100644 ---- gcc/cfgcleanup.c -+++ gcc/cfgcleanup.c -@@ -2001,6 +2001,15 @@ 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) -+ return false; -+#endif -+ - /* Replace references to LABEL1 with LABEL2. */ - for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) - { -@@ -2016,8 +2025,9 @@ 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)) -+ ) - redirect_to = src2; - else - { -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); - } - -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 bf3f32da08ac..7aa190620911 100644 ---- gcc/config.gcc -+++ gcc/config.gcc -@@ -1940,6 +1940,27 @@ 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" -+ 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 -+ CFLAGS="-Os" -+ ;; - 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 100644 -index 000000000000..e5cd6e950b52 ---- /dev/null -+++ gcc/config/m68k/amigaos-protos.h -@@ -0,0 +1,55 @@ -+/* 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, 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), (INDIRECT))) -+ -+#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 100644 -index 000000000000..28d20a980978 ---- /dev/null -+++ gcc/config/m68k/amigaos.c -@@ -0,0 +1,931 @@ -+/* 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 "langhooks.h" -+#include "function.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 -+ -+//----- 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); -+ } -+ } -+ -+ -+//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 = decl == current_function_decl; -+ cum->num_of_regs = amigaos_regparm > 0 ? amigaos_regparm : 0; -+ 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. -+ For a library call, FNTYPE is 0. */ -+ -+ cum->last_arg_reg = -1; -+ cum->regs_already_used = 0; -+ -+ if (fntype) -+ { -+ tree attrs = TYPE_ATTRIBUTES(fntype); -+ if (attrs) -+ { -+ 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 && DECL_STATIC_CHAIN(fntype)) -+ { -+ 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); -+ else -+ /* Call to compiler-support function. */ -+ cum->formal_type = 0; -+ 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 -+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", 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; -+ } -+ -+ 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 (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 == cum->num_of_regs && 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 = *get_cumulative_args (cum_v) ? &mycum : &othercum; -+ -+ 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; -+ 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) -+{ -+ 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)))); -+ } -+} -+ -+/* 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 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) -+ { -+ 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 (asm2) -+ 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 */ -+ -+/* 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) -+{ -+ 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)) -+ { -+ 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 -+ { -+ warning (OPT_Wattributes, "`%s' attribute only applies to data", IDENTIFIER_POINTER(name)); -+ } -+ } -+ else -+ { -+ if (is_attribute_p ("chip", name) || is_attribute_p ("fast", name) || is_attribute_p ("far", name)) -+ { -+ // OK -+ } -+ 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 ; -+} -+ -+#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) -+{ -+ if (!*attr) -+ return; -+ -+ tree name = TREE_PURPOSE(*attr); -+ -+ if (is_attribute_p("chip", name) || is_attribute_p("far", name) || is_attribute_p("fast", name)) -+ { -+ if (!TREE_TYPE(decl) == VAR_DECL) -+ { -+ error ("`%s' attribute can only be specified for variables", IDENTIFIER_POINTER(name)); -+ return; -+ } -+ -+ if (! TREE_STATIC (decl) && ! DECL_EXTERNAL (decl)) -+ { -+ 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) -+ set_decl_section_name(decl, section_name); -+ else if (strcmp (DECL_SECTION_NAME (decl), section_name) ) -+ { -+ error_at (DECL_SOURCE_LOCATION(decl), -+ "`%s' attribute conflicts with previous declaration", IDENTIFIER_POINTER(name)); -+ } -+ } -+ else -+ { -+// warning (OPT_Wattributes, "`%s' attribute unknown", IDENTIFIER_POINTER(name)); -+ } -+} -+ -+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. */ -+#ifndef TARGET_AMIGAOS_VASM -+extern void -+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"; -+ -+ 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 -+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. */ -+ -+/** -+ * 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 cnst) -+{ -+ if (flag_pic < 3) -+ return false; -+ 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. -+ -+ 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; -+} -+ -+rtx -+amigaos_struct_value_rtx (tree fntype, int incoming ATTRIBUTE_UNUSED) -+{ -+ return gen_rtx_REG (Pmode, M68K_STRUCT_VALUE_REGNUM); -+} -+ -+rtx -+amigaos_static_chain_rtx (const_tree decl, bool incoming ATTRIBUTE_UNUSED) -+{ -+ if (!decl || !DECL_STATIC_CHAIN(decl)) -+ return 0; -+ -+ 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; -+ -+ 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); -+ if (!(used & (1 << 14))) -+ return gen_rtx_REG (Pmode, 14); -+ -+ return 0; -+} -+ -+/** -+ * 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_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 (amiga_is_const_pic_ref(x)) -+ return GET_CODE(y) == CONST_INT; -+ -+ return amigaos_legitimate_src(x) && amigaos_legitimate_src(y) && !amiga_is_const_pic_ref(y); -+ } -+ -+ 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 || GET_CODE(x) == SIGN_EXTEND) -+ { -+ rtx reg = XEXP(x, 0); -+ if (!REG_P(reg)) -+ return true; -+ -+ return false; -+ } -+ } -+ -+ if (GET_CODE(op) == UNSPEC) -+ return false; -+ } -+ -+ return true; -+} -+ -+void -+amigaos_restore_a4 (void) -+ { -+ if (flag_pic >= 3 && !flag_resident) -+ { -+ 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 ___a4_init,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 -+ } -+ -+#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/amigaos.h b/gcc/config/m68k/amigaos.h -new file mode 100644 -index 000000000000..1b60ed633a3a ---- /dev/null -+++ gcc/config/m68k/amigaos.h -@@ -0,0 +1,504 @@ -+/* 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). -+ 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") } -+ -+ -+/* 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); -+ -+#undef TARGET_ASM_NAMED_SECTION -+#define TARGET_ASM_NAMED_SECTION amiga_named_section -+ -+/* 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) -+ -+/* 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) (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 short" -+ -+/* XXX: section support */ -+#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 -+#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) -+ -+#if 0 -+ -+/* 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_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 */ -+ -+ -+#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)) -+ -+ -+/* -+ 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 (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) \ -+ 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 \ -+ { "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 }, \ -+ { "stkparm", 0, 0, false, true, true, amigaos_handle_type_attribute,\ -+ true }, -+ -+#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); -+ -+#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); -+ -+ -+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))) -+ -+#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/amigaos.opt b/gcc/config/m68k/amigaos.opt -new file mode 100644 -index 000000000000..07406d27a777 ---- /dev/null -+++ gcc/config/m68k/amigaos.opt -@@ -0,0 +1,63 @@ -+ -+mregparm= -+Target RejectNegative Var(amigaos_regparm) Joined UInteger Init(-1) -+Pass arguments through registers. -+ -+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 -+ -+fbaserel -+Target Report Var(flag_pic,3) -+data is addressed relative to a4 -+ -+fbaserel32 -+Target Report Var(flag_pic,4) -+data is addressed relative to a4 with 32 bit offsets -+ -+resident -+Target Common Report Var(flag_resident,3) -+data is addressed relative to a4, linked as resident -+ -+resident32 -+Target Common Report Var(flag_resident,4) -+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 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 -+Default: -fbbb=+ which yields -fbbb=abcefimprs -diff --git a/gcc/config/m68k/constraints.md b/gcc/config/m68k/constraints.md -index b62120895304..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. - -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..4533427db7a7 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_AMIGA -+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; -@@ -186,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 -@@ -322,6 +331,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 +345,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 } - }; - -@@ -340,11 +356,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) - -@@ -545,7 +571,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) -@@ -556,7 +582,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. */ -@@ -569,11 +595,15 @@ 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; -- -+#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. */ -@@ -866,8 +896,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 -@@ -978,6 +1009,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) - { -@@ -986,6 +1019,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; -@@ -1021,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. */ -@@ -1030,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, -@@ -1127,9 +1173,14 @@ 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)); -+ -+#ifdef TARGET_AMIGA -+ amigaos_restore_a4 (); -+#endif - } - - /* Return true if a simple (return) instruction is sufficient for this -@@ -1419,6 +1470,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 +1492,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. */ -@@ -1796,13 +1849,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 -@@ -1921,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) - { -@@ -2111,6 +2174,18 @@ 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; -+ -+ if (!amigaos_legitimate_src(x)) -+ return false; -+ -+#endif -+ - return m68k_decompose_address (mode, x, strict_p, &address); - } - -@@ -2131,7 +2206,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 -@@ -2172,6 +2251,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 +2523,37 @@ legitimize_pic_address (rtx orig, machine_mode mode ATTRIBUTE_UNUSED, - if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF) - { - gcc_assert (reg); -+ 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 -+ { -+ -+ /* SBF: Does the symbol use common or bss and qualifies for pic_reg? -+ * Do not ref to .text via pic_reg! -+ */ -+ 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) -+ { - -- pic_ref = m68k_wrap_symbol_into_got_ref (orig, RELOC_GOT, reg); -- pic_ref = m68k_move_to_reg (pic_ref, orig, reg); -+ /* 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) - { -@@ -2463,7 +2572,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); -@@ -2787,7 +2897,10 @@ const_int_cost (HOST_WIDE_INT i) - } - } - --static bool -+#ifndef TARGET_AMIGA -+static -+#endif -+bool - m68k_rtx_costs (rtx x, machine_mode mode, int outer_code, - int opno ATTRIBUTE_UNUSED, - int *total, bool speed ATTRIBUTE_UNUSED) -@@ -2863,6 +2976,7 @@ m68k_rtx_costs (rtx x, machine_mode mode, int outer_code, - *total = COSTS_N_INSNS (TARGET_COLDFIRE ? 2 : 3); - return true; - } -+ - return false; - - case ASHIFT: -@@ -2931,6 +3045,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; - } -@@ -4456,7 +4589,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) -@@ -4475,34 +4610,52 @@ 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)) -- fprintf (file, MOTOROLA ? ".l" : ":l"); -+ && INTVAL (XEXP (op, 0)) >= -0x8000) -+#ifdef TARGET_AMIGA -+/* SBF: Do not append some 'l' with baserel(32). */ -+ && !amiga_is_const_pic_ref(XEXP(op, 0)) -+#endif -+ ) -+ fprintf (file, MOTOROLA ? ".l" : ":l"); - } - else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode) - { - 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 - { - /* 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 -@@ -4521,7 +4674,19 @@ m68k_get_reloc_decoration (enum m68k_reloc reloc) - switch (reloc) - { - case RELOC_GOT: -- if (MOTOROLA) -+ /* 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) - return "@GOT.w"; -@@ -4671,8 +4836,58 @@ print_operand_address (FILE *file, rtx addr) - { - struct m68k_address address; - -+#ifdef TARGET_AMIGA -+ /* -+ * SBF: remove the const wrapper. -+ */ -+ if (amiga_is_const_pic_ref(addr)) -+ { -+ /* 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 && 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)); -+ 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 (); -+ { -+ debug_rtx(addr); -+ gcc_unreachable (); -+ } - - if (address.code == PRE_DEC) - fprintf (file, MOTOROLA ? "-(%s)" : "%s@-", -@@ -4714,6 +4929,14 @@ print_operand_address (FILE *file, rtx addr) - } - else - output_addr_const (file, addr); -+ -+#ifdef TARGET_AMIGA -+ if (SYMBOL_REF_FUNCTION_P(addr)) -+ { -+ if (flag_smallcode) -+ asm_fprintf(file, ":w(pc)"); -+ } -+#endif - } - } - else -@@ -5155,7 +5378,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) -@@ -5169,7 +5394,7 @@ m68k_regno_mode_ok (int regno, machine_mode mode) - else if (ADDRESS_REGNO_P (regno)) - { - if (regno + GET_MODE_SIZE (mode) / 4 <= 16) -- return true; -+ return !frame_pointer_needed || regno != FRAME_POINTER_REGNUM; - } - else if (FP_REGNO_P (regno)) - { -@@ -5190,6 +5415,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.h b/gcc/config/m68k/m68k.h -index 2aa858fa23b5..442a84e6a883 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. */ -@@ -378,14 +382,13 @@ along with GCC; see the file COPYING3. If not see - { /* 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\ - } - -- - /* On the m68k, ordinary registers hold 32 bits worth; - for the 68881 registers, a single register is always enough for - anything that can be stored in them at all. */ -@@ -440,8 +443,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 +452,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 +461,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 */ \ -@@ -614,11 +619,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) \ -@@ -727,9 +732,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" -@@ -739,6 +784,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", \ -@@ -858,11 +914,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. */ -@@ -872,13 +934,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)), \ -@@ -971,3 +1044,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..05ef02027f01 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) - ]) -@@ -1566,7 +1564,7 @@ - ;; 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"))] - "" - "pea %a1" -@@ -7204,6 +7202,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 +7212,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]))) -+ && !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 -new file mode 100644 -index 000000000000..3f3aafc5f254 ---- /dev/null -+++ gcc/config/m68k/m68kamigaos.h -@@ -0,0 +1,760 @@ -+/* 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 -+ -+#define HAS_INIT_SECTION -+ -+#ifndef SWBEG_ASM_OP -+#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 -+ -+#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 -+#ifndef TARGET_AMIGAOS_VASM -+#define LOCAL_LABEL_PREFIX "." -+#else -+#define LOCAL_LABEL_PREFIX "_." -+#endif -+ -+/* 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. */ -+ -+#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; -+ -+#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. */ -+ -+#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" -+ -+#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 -+ 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 -+#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. */ -+ -+#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 */ -+ -+#ifndef TARGET_AMIGAOS_VASM -+#undef BSS_SECTION_ASM_OP -+#define BSS_SECTION_ASM_OP "\t.bss" -+#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) -+#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 ("__fast=__attribute__((__fast__))"); \ -+ builtin_define ("__far=__attribute__((__far__))"); \ -+ builtin_define ("__saveds=__attribute__((__saveds__))"); \ -+ builtin_define ("__interrupt=__attribute__((__interrupt__))"); \ -+ builtin_define ("__stackext=__attribute__((__stackext__))"); \ -+ builtin_define ("__regargs=__attribute__((__regparm__(2)))"); \ -+ builtin_define ("__stdargs=__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 -+ -+/* put return values in FPU build in FP0 Reg */ -+#undef FUNCTION_VALUE_REGNO_P -+#define FUNCTION_VALUE_REGNO_P(N) \ -+ ((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. */ -+ -+//#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) -+*/ -+ -+/* 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__} " \ -+ "%{!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:%(cpp_libnix)} " \ -+ "%{mcrt=nix*:%(cpp_libnix)} " \ -+ "%{mcrt=ixemul:%(cpp_ixemul)} " \ -+ "%{mcrt=clib2:%(cpp_clib2)} " \ -+ "%{!noixemul:%{!mcrt*:%(cpp_clib2)}}" -+ -+/* 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} %{!msmall-code:-S}" -+#else -+#define ASM_SPEC \ -+ "-gas -esc -ldots -Fhunk -quiet %(asm_cpu) %(asm_cpu_default) %{msmall-code:-sc}" -+#endif -+ -+#undef ASM_CPU_SPEC -+#define ASM_CPU_SPEC \ -+ "%{mcpu=*:-m%*} " \ -+ "%{m68000|mc68000:-m68010} " \ -+ "%{m6802*|mc68020:-m68020} " \ -+ "%{m68030} " \ -+ "%{m68040} " \ -+ "%{m68060}" -+ -+#ifndef TARGET_AMIGAOS_VASM -+#define ASM_CPU_DEFAULT_SPEC \ -+ "%{!m680*:%{!mc680*:%{!mcpu=*:-m68000}}}" -+#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 -+ 32-bit versions, libnix, profiling or plain crt0.o. */ -+ -+#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(libnix/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:" \ -+ "%{fbaserel32:nlbcrt0.o%s}" \ -+ "%{!fbaserel32: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 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)} " \ -+ "%{!noixemul:%{!mcrt*:%(startfile_clib2)}}" -+#endif -+ -+#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)} " \ -+ "%{!noixemul:%{!mcrt*:%(endfile_clib2)}}" -+ -+ -+/* 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. */ -+ -+#define LIB_IXEMUL_SPEC \ -+ "%{!p:%{!pg:-lc -lamiga -lc}} " \ -+ "%{p:-lc_p} %{pg:-lc_p}" -+#define LIB_LIBNIX_SPEC \ -+ "-lnixmain -lnix " \ -+ "%{mcrt=*:-l%*} " \ -+ "%{!mcrt=*:-lnix20} " \ -+ "-lamiga " \ -+ "%{mstackcheck:-lstack} " \ -+ "%{mstackextend:-lstack}" -+#define LIB_CLIB2_SPEC \ -+ "-lc -lamiga -ldebug " \ -+ "%{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)} " \ -+ "%{!noixemul:%{!mcrt*:%(lib_clib2)}}" -+#endif -+ -+#define LIBGCC_IXEMUL_SPEC "" -+#define LIBGCC_LIBNIX_SPEC "-lnix -fl libnix " \ -+ "%{mcrt=*:-l%*} " \ -+ "%{!mcrt=*:-lnix20} -lstubs" -+#define LIBGCC_CLIB2_SPEC "-lc" -+#define LIBGCC_SPEC "-lgcc " \ -+ "%{noixemul:%(libgcc_libnix)} " \ -+ "%{mcrt=nix*:%(libgcc_libnix)} " \ -+ "%{mcrt=ixemul:%(libgcc_ixemul)} " \ -+ "%{mcrt=clib2:%(libgcc_clib2)} " \ -+ "%{!noixemul:%{!mcrt*:%(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. */ -+ -+#ifdef TARGET_AMIGAOS_VASM -+#define LINK_SPEC \ -+ "%{noixemul:%(link_libnix)} " \ -+ "%{mcrt=nix*:%(link_libnix)} " \ -+ "%{mcrt=ixemul:%(link_ixemul)} " \ -+ "%{mcrt=clib2:%(link_clib2)} " \ -+ "%{!noixemul:%{!mcrt*:%(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 -+#define LINK_SPEC \ -+ "%{noixemul:%(link_libnix)} " \ -+ "%{mcrt=nix*:%(link_libnix)} " \ -+ "%{mcrt=ixemul:%(link_ixemul)} " \ -+ "%{mcrt=clib2:%(link_clib2)} " \ -+ "%{!noixemul:%{!mcrt*:%(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}} " \ -+ "%{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} " \ -+ "%{m68040:-fl libm020} " \ -+ "%{m68060:-fl libm020} " \ -+ "%{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. */ -+ -+#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. */ -+ -+#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:" \ -+ "%{!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*} }}}}}} " -+#endif -+ -+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 -+ 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 }, \ -+ {"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 */ -+ -+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) -+ -+#undef FIXED_INCLUDE_DIR -+#define FIXED_INCLUDE_DIR CROSS_INCLUDE_DIR "/../../include" -+ -+// 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 \ -+ )) -+ -+ -+ -+/* Given that symbolic_operand(X), return TRUE if no special -+ base relative relocation is necessary */ -+ -+#undef LEGITIMATE_PIC_OPERAND_P -+#define LEGITIMATE_PIC_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))) || -+ -+#undef TARGET_GCC_EXCEPT_TABLE -+#define TARGET_GCC_EXCEPT_TABLE ".text" -+ -+#undef TARGET_GCC_EXCEPT_TABLE_S -+#define TARGET_GCC_EXCEPT_TABLE_S ".text" -+ -+#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); -+ -+//extern bool debug_recog(char const * txt, int which_alternative, int n, rtx * operands); -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/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; -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); - }) - -diff --git a/gcc/config/m68k/t-amigaos b/gcc/config/m68k/t-amigaos -new file mode 100755 -index 000000000000..bf9c5279d04f ---- /dev/null -+++ gcc/config/m68k/t-amigaos -@@ -0,0 +1,28 @@ -+# 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 -+ -+### 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 -+ -+# 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 -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/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. -diff --git a/gcc/df-scan.c b/gcc/df-scan.c -index 98de84405428..1f23452afe19 100644 ---- gcc/df-scan.c -+++ gcc/df-scan.c -@@ -1807,6 +1807,12 @@ 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)) -+ { -+ --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/dwarf2out.c b/gcc/dwarf2out.c -index f241073866b4..566aaaf4e370 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 -@@ -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); -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); - } -diff --git a/gcc/except.c b/gcc/except.c -index 2a1073f80cc4..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; - -@@ -2850,14 +2851,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/final.c b/gcc/final.c -index 55cf509611f7..fa8b2964a40d 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,12 @@ 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 *); -+ -+ extern bool dump_reg_track; -+ void append_reg_cache (FILE * f, rtx_insn * insn); -+ - const char *p; - int c; - #ifdef ASSEMBLER_DIALECT -@@ -3778,6 +3786,11 @@ 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); -+ 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) - output_asm_operand_names (operands, oporder, ops); -@@ -3995,6 +4008,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"); - } - } -diff --git a/gcc/function.c b/gcc/function.c -index 6942a504127f..ebe3e1c37121 100644 ---- gcc/function.c -+++ gcc/function.c -@@ -39,9 +39,9 @@ along with GCC; see the file COPYING3. If not see - #include "rtl.h" - #include "tree.h" - #include "gimple-expr.h" -+#include "tm_p.h" - #include "cfghooks.h" - #include "df.h" --#include "tm_p.h" - #include "stringpool.h" - #include "expmed.h" - #include "optabs.h" -diff --git a/gcc/gcc.c b/gcc/gcc.c -index 85ea19bd3a09..a4da7d515ce5 100644 ---- gcc/gcc.c -+++ gcc/gcc.c -@@ -10107,3 +10107,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, "", NULL); -+ 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-unknown-amigaos/", NULL); -+ } -+ } -+ } -+ free(glp); -+ } -+ if (!p) -+ p = concat("../../../../", "", NULL); -+ -+ for (int i = 0; i < argc; ++i) { -+ char * q = concat(p, argv[i], NULL); -+ free(p); -+ p = q; -+ } -+// printf("amiga_m68k_prefix_func='%s'\n", p); -+ return p; -+} -+#endif -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 -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 -diff --git a/gcc/hwint.h b/gcc/hwint.h -index 4dd255d486c5..d5296a81d08e 100644 ---- gcc/hwint.h -+++ gcc/hwint.h -@@ -295,7 +295,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 */ -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/opts.c b/gcc/opts.c -index 8f9862db57c2..6a87349e6a70 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 }, -diff --git a/gcc/passes.c b/gcc/passes.c -index e89618111245..1d53bb23b1b0 100644 ---- gcc/passes.c -+++ gcc/passes.c -@@ -2269,6 +2269,29 @@ 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 set= single_set (insn); -+ if (!set) -+ continue; -+ -+ if (amiga_is_const_pic_ref(SET_SRC(set)) && MEM_P(SET_DEST(set))) -+ debug_rtx(insn); -+ } -+#endif -+ } -+} -+ -+ - /* Execute PASS. */ - - bool -@@ -2278,6 +2301,9 @@ execute_one_pass (opt_pass *pass) - - bool gate_status; - -+ 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. */ - if (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS) -diff --git a/gcc/passes.def b/gcc/passes.def -index 7db9c9577cf4..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) -@@ -458,6 +459,7 @@ along with GCC; see the file COPYING3. If not see - NEXT_PASS (pass_cprop_hardreg); - 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); -diff --git a/gcc/recog.c b/gcc/recog.c -index 92b2aa31a777..73d1fd1b1336 100644 ---- gcc/recog.c -+++ gcc/recog.c -@@ -3252,6 +3252,7 @@ peep2_attempt (basic_block bb, rtx_insn *insn, int match_len, rtx_insn *attempt) - /* 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/regrename.c b/gcc/regrename.c -old mode 100644 -new mode 100755 -index 9643f328ea3e..1ed6557ee713 ---- gcc/regrename.c -+++ gcc/regrename.c -@@ -374,44 +374,45 @@ find_rename_reg (du_head_p this_head, enum reg_class super_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. */ -+ 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)) - 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 -+ 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)) -- continue; -+ 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. */ -- if ((pass == 0 -+ /* 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) - && !TEST_HARD_REG_BIT (reg_class_contents[preferred_class], - best_new_reg)) - || tick[best_new_reg] > tick[new_reg]) -- best_new_reg = new_reg; -+ best_new_reg = new_reg; - } - if (pass == 0 && best_new_reg != old_reg) - break; -@@ -897,7 +898,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; -@@ -921,7 +922,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]); - } - -@@ -954,7 +955,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; -@@ -962,19 +963,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; - } -@@ -983,10 +985,29 @@ 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. */ -+ 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) && VAR_LOC_UNKNOWN_P(INSN_VAR_LOCATION_LOC(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); -+ } -+ -+ /* 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; - } - -@@ -1912,7 +1933,6 @@ const pass_data pass_data_regrename = - 0, /* todo_flags_start */ - TODO_df_finish, /* todo_flags_finish */ - }; -- - class pass_regrename : public rtl_opt_pass - { - public: -@@ -1923,7 +1943,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 (); } -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 -diff --git a/gcc/tree-chkp.c b/gcc/tree-chkp.c -index 28dac22add66..16aa71ca4ee4 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/tree-pass.h b/gcc/tree-pass.h -index 5f5055d3a6c1..76c0996850f4 100644 ---- gcc/tree-pass.h -+++ gcc/tree-pass.h -@@ -590,6 +590,8 @@ 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_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); -diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c -index 9f09d30b1f91..ab9c0117b078 100644 ---- gcc/var-tracking.c -+++ gcc/var-tracking.c -@@ -92,10 +92,10 @@ - #include "target.h" - #include "rtl.h" - #include "tree.h" -+#include "tm_p.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/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; -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 -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 6f6810cf0baf..7117e7983b53 100644 ---- libgcc/config.host -+++ libgcc/config.host -@@ -816,6 +816,11 @@ m32r-*-linux*) - m32rle-*-linux*) - tmake_file="$tmake_file m32r/t-linux t-fdpbit" - ;; -+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) - tmake_file="$tmake_file m68k/t-floatlib" - ;; -diff --git a/libgcc/config/m68k/fpgnulib.c b/libgcc/config/m68k/fpgnulib.c -index fe41edf26aa0..90926104d8fd 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 */ - -@@ -396,6 +418,8 @@ float __truncdfsf2 (double); - long __fixdfsi (double); - long __fixsfsi (float); - -+#if !defined(EXTFLOATCMP) -+ - int - __unordxf2(long double a, long double b) - { -@@ -445,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) -@@ -549,6 +541,8 @@ __negxf2 (long double x1) - return - (double) x1; - } - -+#else -+ - long - __cmpxf2 (long double x1, long double x2) - { -@@ -591,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 1ee8782d9fd2..2365433a59b3 100644 ---- libgcc/config/m68k/t-floatlib -+++ libgcc/config/m68k/t-floatlib -@@ -1,11 +1,62 @@ --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 = 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 - --xfgnulib.c: $(srcdir)/config/m68k/fpgnulib.c -- echo '#define EXTFLOAT' > xfgnulib.c -- cat $< >> xfgnulib.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 -diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c -index 1fb6026d123f..7bf0e4236f64 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,75 @@ 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); - } - - -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; -+} -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 -diff --git a/libstdc++-v3/config/os/newlib/ctype_configure_char.cc b/libstdc++-v3/config/os/newlib/ctype_configure_char.cc -index 903de5625d77..ed0c757d42f8 100644 ---- libstdc++-v3/config/os/newlib/ctype_configure_char.cc -+++ libstdc++-v3/config/os/newlib/ctype_configure_char.cc -@@ -65,6 +65,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION - _M_narrow_ok = 0; - } - -+#ifdef __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 b/libstdc++-v3/configure -index 9bf152a01573..f162705f2625 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 - ;; -@@ -28883,6 +28885,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. - ;; -diff --git a/libstdc++-v3/configure.host b/libstdc++-v3/configure.host -index 304a7f5aff61..fde4a72bd31b 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" -+ CFLAGS="-Os -noixemul" -+ CPPFLAGS="-Os -noixemul" -+ ;; - bsd*) - # Plain BSD attempts to share FreeBSD files. - os_include_dir="os/bsd/freebsd" -diff --git a/libstdc++-v3/include/tr1/cstdint b/libstdc++-v3/include/tr1/cstdint -index 7304d9008413..7d6ab77ce17a 100644 ---- libstdc++-v3/include/tr1/cstdint -+++ libstdc++-v3/include/tr1/cstdint -@@ -30,7 +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) -diff --git a/libstdc++-v3/src/c++11/ctype.cc b/libstdc++-v3/src/c++11/ctype.cc -index fa370681dad5..f80e83034255 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 __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 -- cgit v1.2.3