Index: Makefile.riscpkg =================================================================== RCS file: Makefile.riscpkg diff -N Makefile.riscpkg --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Makefile.riscpkg 15 Feb 2005 14:34:29 -0000 1.2 @@ -0,0 +1,29 @@ +# This file is part of the RISC OS Packaging Project distribution of GCC. +# Copyright © 2005 Graham Shaw. +# Distribution and use are subject to the same terms as GCC as a whole. + +VERSION = 2_95_3 + +all: + mkdir -p libiberty/stage1 + make -C libiberty/stage1 -f ../Makefile.riscpkg stage=stage1 + mkdir -p gcc/autogen + make -C gcc/autogen -f ../Makefile.riscpkg stage=autogen + mkdir -p gcc/stage1 + make -C gcc/stage1 -f ../Makefile.riscpkg dirs + make -C gcc/stage1 -f ../Makefile.riscpkg stage=stage1 + mkdir -p libiberty/stage2 + make -C libiberty/stage2 -f ../Makefile.riscpkg stage=stage2 + mkdir -p gcc/stage2 + make -C gcc/stage2 -f ../Makefile.riscpkg dirs + make -C gcc/stage2 -f ../Makefile.riscpkg stage=stage2 + mkdir -p libiberty/stage3 + make -C libiberty/stage3 -f ../Makefile.riscpkg stage=stage3 + mkdir -p gcc/stage3 + make -C gcc/stage3 -f ../Makefile.riscpkg dirs + make -C gcc/stage3 -f ../Makefile.riscpkg stage=stage3 + mkdir -p libio/stage3 + make -C libio/stage3 -f ../Makefile.riscpkg stage=stage3 + mkdir -p libstdc++/stage3 + mkdir -p libstdc++/stage3/std + make -C libstdc++/stage3 -f ../Makefile.riscpkg stage=stage3 Index: !GCC/!Boot,feb =================================================================== RCS file: !GCC/!Boot,feb diff -N !GCC/!Boot,feb --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ !GCC/!Boot,feb 19 Feb 2005 19:08:32 -0000 1.4 @@ -0,0 +1,11 @@ +| This file is part of the RISC OS Packaging Project distribution of GCC. +| Copyright © 2005 Graham Shaw. +| Distribution and use are subject to the GNU General Public License, +| a copy of which may be found in the file ".GPL-2". + +If "" = "" Then Set GCC$Dir +If "" = "" Then Set GCC$Path . +IfThere .bin.gcc Then If "" = "" Then Set Alias$gcc /.bin.gcc %%*0 +IfThere .bin.g++ Then If "" = "" Then Set Alias$g++ /.bin.g++ %%*0 +IfThere .bin.cpp Then If "" = "" Then Set Alias$cpp /.bin.cpp %%*0 +IconSprites .!Sprites Index: !GCC/!Run,feb =================================================================== RCS file: !GCC/!Run,feb diff -N !GCC/!Run,feb --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ !GCC/!Run,feb 19 Feb 2005 19:08:32 -0000 1.4 @@ -0,0 +1,11 @@ +| This file is part of the RISC OS Packaging Project distribution of GCC. +| Copyright © 2005 Graham Shaw. +| Distribution and use are subject to the GNU General Public License, +| a copy of which may be found in the file ".GPL-2". + +Set GCC$Dir +Set GCC$Path . +IfThere .bin.gcc Then Set Alias$gcc /.bin.gcc %%*0 +IfThere .bin.g++ Then Set Alias$g++ /.bin.g++ %%*0 +IfThere .bin.cpp Then Set Alias$cpp /.bin.cpp %%*0 +IconSprites .!Sprites Index: !GCC/!Sprites.uue =================================================================== RCS file: !GCC/!Sprites.uue diff -N !GCC/!Sprites.uue --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ !GCC/!Sprites.uue 15 Feb 2005 19:30:47 -0000 1.1 @@ -0,0 +1,12 @@ +begin 707 !GCC/!Sprites,ff9 +M`0```!````"0`0``@`$``"%G8V,```````````0````0``````````<````L +M````+`````P````````````````````````````````S```````````````` +M`#,`````````L+L`"P`+"P`+````````````,P`+``"[``L+``L````S```` +M``````NP"PL+"PL`"P```````````#,`"P`+"[`+"P`+````,P````````"P +MNP`+``NPNP`````````````S`````````````````#,`````````.GPL-2". + +If "" = "" Then Set LibIberty$Dir +If "" = "" Then Set LibIberty$Path .,.include. +IconSprites .!Sprites Index: !LibIberty/!Run,feb =================================================================== RCS file: !LibIberty/!Run,feb diff -N !LibIberty/!Run,feb --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ !LibIberty/!Run,feb 19 Feb 2005 19:44:34 -0000 1.1 @@ -0,0 +1,8 @@ +| This file is part of the RISC OS Packaging Project distribution of GCC. +| Copyright © 2005 Graham Shaw. +| Distribution and use are subject to the GNU General Public License, +| a copy of which may be found in the file ".GPL-2". + +Set LibIberty$Dir +Set LibIberty$Path .,.include. +IconSprites .!Sprites Index: !LibIberty/!Sprites.uue =================================================================== RCS file: !LibIberty/!Sprites.uue diff -N !LibIberty/!Sprites.uue --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ !LibIberty/!Sprites.uue 19 Feb 2005 19:44:34 -0000 1.1 @@ -0,0 +1,12 @@ +begin 707 !LibIberty/!Sprites,ff9 +M`0```!````"0`0``@`$``"%L:6)I8F5R='D```0````0``````````<````L +M````+`````P````````````````````````````````S```````````````` +M`#,`````````!P``!P``````````````````,P`'``<'```````````S```` +M``````<``'<#`````````````````#,`!P`'!P<`````````,P````````!W +M!P=W`P`````````````````S`````````````````#,`````````=P<'```` +M```'````````````,P!P``<```````<````S`````````'``=P-S`W,#=W!P +M`````````#,`<``'!S<'!P`'<'``,P````````!W!W<#.GPL-2". + +If "" = "" Then Set LibStdCxx$Dir +If "" = "" Then Set LibStdCxx$Path .,.include. +IconSprites .!Sprites Index: !LibStdC++/!Run,feb =================================================================== RCS file: !LibStdC++/!Run,feb diff -N !LibStdC++/!Run,feb --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ !LibStdC++/!Run,feb 20 Feb 2005 20:21:21 -0000 1.2 @@ -0,0 +1,8 @@ +| This file is part of the RISC OS Packaging Project distribution of GCC. +| Copyright © 2005 Graham Shaw. +| Distribution and use are subject to the GNU General Public License, +| a copy of which may be found in the file ".GPL-2". + +Set LibStdCxx$Dir +Set LibStdCxx$Path .,.include. +IconSprites .!Sprites Index: !LibStdC++/!Sprites.uue =================================================================== RCS file: !LibStdC++/!Sprites.uue diff -N !LibStdC++/!Sprites.uue --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ !LibStdC++/!Sprites.uue 19 Feb 2005 19:48:06 -0000 1.2 @@ -0,0 +1,12 @@ +begin 707 !LibStdC++/!Sprites,ff9 +M`0```!````"0`0``@`$``"%L:6)S=&1C*RL```0````0``````````<````L +M````+`````P````````````````````````````````S```````````````` +M`#,`````````!P`'!P!S1W```'``````````,P`'```'``<@<```<``S```` +M``````<`!W<#<`=P=S!W`````````#,`!P`'!P<"<'``<'``,P````````!W +M!P=W`W0W,' +Standards-Version: 0.1.0 +Version: 2.95.3-0 +Description: The GCC Software Development Kit for RISC OS. + GCC is the GNU Compiler Collection. It includes front ends for C, + C++, Objective-C, Fortran, Java and Ada, as well as standard + libraries for these languages. + . + GCCSDK is a port of GCC to RISC OS. Additions include an + APCS-compatible back end, tools for manipulating AOF files, and + the compatibility library UnixLib. + +Package: GCC-Common +Description: Common files required for the GNU Compiler Collection. + +Package: CPP +Depends: CPP-2.95 +Description: The GNU C Preprocessor front end. + +Package: CPP-2.95 +Depends: CPP (>= 2.95.3) +Description: The GNU C Preprocessor back end, version 2.95. + +Package: GCC +Depends: CPP-2.95, GCC-2.95 +Recommends: Ld-GCCSDK (>= 2.22), As +Description: The GNU C Compiler front end. + +Package: GCC-2.95 +Depends: GCC (>= 2.95.3) +Recommends: UnixLib-Dev (>= 4.0) +Description: The GNU C Compiler back end, version 2.95. + +Package: G++ +Depends: CPP-2.95, GCC-2.95, G++-2.95 +Recommends: Ld-GCCSDK, As +Description: The GNU C++ Compiler front end. + +Package: G++-2.95 +Depends: G++ (>= 2.95.3), LibStdC++-Dev (>= 2.10) +Description: The GNU C++ Compiler back end, version 2.95. + +Package: LibIberty-Dev +Description: A collection of subroutines from the GNU project. + +Package: LibStdC++-Dev +Description: The GNU C++ Standard Library +Version: 2.10.0-0 Index: RiscPkg/Copyright =================================================================== RCS file: RiscPkg/Copyright diff -N RiscPkg/Copyright --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ RiscPkg/Copyright 19 Feb 2005 19:46:24 -0000 1.2 @@ -0,0 +1,101 @@ +This is the RISC OS Packaging Project distribution of GCC (version 2.95). + +GCC is published by the Free Software Foundation. + +GCC was originally written by Richard Stallman, with the first +release occurring in 1987. A list of current maintainers can +be found in the file 'MAINTAINERS' within the GCC-2.95 source +package. + +The upstream sources were downloaded from the URL: + +ftp://ftp.gnu.org/gnu/gcc/gcc-2.95.3.tar.gz + +on 7th February 2005. + +RISC OS-specific patches were obtained from GCCSDK, +which is maintained by Nick Burrett. They were exported +by anonymous CVS from: + +:pserver:anoncvs@gccsdk.riscos.info:/usr/local/cvsroot + +from the release_2_95 branch. + +There is a homepage for GCC at the URL: + +http://gcc.gnu.org/ + +and for GCCSDK at the URL: + +http://gccsdk.riscos.info/ + +Distribution and use are subject to the GNU General Public License, +a copy of which may be found in the file ".GPL-2". + +The following exception to the General Public Licence applies to the +run-time libraries libgcc, libio, libiostream, libstdc++, libobjc +and libchill: + +== begin == +As a special exception, if you link this library with other files, +some of which are compiled with GCC, to produce an executable, +this library does not by itself cause the resulting executable +to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. +== end == + +Large parts of the library libstdc++ were written by Silicon Graphics +Computer Systems and/or the Hewlett-Packard Company and are subject +to the following licences: + +== begin == +Copyright (c) 1996,1997,1998 +Silicon Graphics Computer Systems, Inc. + +Permission to use, copy, modify, distribute and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and +that both that copyright notice and this permission notice appear +in supporting documentation. Silicon Graphics makes no +representations about the suitability of this software for any +purpose. It is provided "as is" without express or implied warranty. +== end == + +== begin == +Copyright (c) 1994 +Hewlett-Packard Company + +Permission to use, copy, modify, distribute and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and +that both that copyright notice and this permission notice appear +in supporting documentation. Hewlett-Packard Company makes no +representations about the suitability of this software for any +purpose. It is provided "as is" without express or implied warranty. +== end == + +The library libf2c is subject to the following licence: + +== begin == +Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. + +Permission to use, copy, modify, and distribute this software +and its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the names of AT&T, Bell Laboratories, +Lucent or Bellcore or any of their entities not be used in +advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +AT&T, Lucent and Bellcore disclaim all warranties with regard to +this software, including all implied warranties of +merchantability and fitness. In no event shall AT&T, Lucent or +Bellcore be liable for any special, indirect or consequential +damages or any damages whatsoever resulting from loss of use, +data or profits, whether in an action of contract, negligence or +other tortious action, arising out of or in connection with the +use or performance of this software. +== end == Index: RiscPkg/G++-2.95.inc =================================================================== RCS file: RiscPkg/G++-2.95.inc diff -N RiscPkg/G++-2.95.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ RiscPkg/G++-2.95.inc 20 Feb 2005 20:23:48 -0000 1.1 @@ -0,0 +1,2 @@ +RiscPkg.* +Apps.Programming.!GCC.gcc-lib.arm-riscos.2/95/3.cc1plus Index: RiscPkg/G++.inc =================================================================== RCS file: RiscPkg/G++.inc diff -N RiscPkg/G++.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ RiscPkg/G++.inc 20 Feb 2005 20:23:48 -0000 1.1 @@ -0,0 +1,3 @@ +RiscPkg.* +SysVars.Alias=24g++ +Apps.Programming.!GCC.bin.g++ Index: RiscPkg/GCC-2.95.inc =================================================================== RCS file: RiscPkg/GCC-2.95.inc diff -N RiscPkg/GCC-2.95.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ RiscPkg/GCC-2.95.inc 20 Feb 2005 20:23:48 -0000 1.1 @@ -0,0 +1,5 @@ +RiscPkg.* +Apps.Programming.!GCC.gcc-lib.arm-riscos.2/95/3.cc1 +Apps.Programming.!GCC.gcc-lib.arm-riscos.2/95/3.a.libgcc +Apps.Programming.!GCC.gcc-lib.arm-riscos.2/95/3.include.* +Apps.Programming.!GCC.gcc-lib.arm-riscos.2/95/3.include.h.* Index: RiscPkg/GCC-Common.inc =================================================================== RCS file: RiscPkg/GCC-Common.inc diff -N RiscPkg/GCC-Common.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ RiscPkg/GCC-Common.inc 20 Feb 2005 20:23:48 -0000 1.1 @@ -0,0 +1,8 @@ +RiscPkg.* +Sprites.!gcc +SysVars.GCC=24Dir +SysVars.GCC=24Path +Apps.Programming.!GCC.!Boot +Apps.Programming.!GCC.!Run +Apps.Programming.!GCC.!Sprites +Apps.Programming.!GCC.!Sprites22 Index: RiscPkg/GCC.inc =================================================================== RCS file: RiscPkg/GCC.inc diff -N RiscPkg/GCC.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ RiscPkg/GCC.inc 20 Feb 2005 20:23:48 -0000 1.1 @@ -0,0 +1,3 @@ +RiscPkg.* +SysVars.Alias=24gcc +Apps.Programming.!GCC.bin.gcc Index: RiscPkg/LibIberty-Dev.inc =================================================================== RCS file: RiscPkg/LibIberty-Dev.inc diff -N RiscPkg/LibIberty-Dev.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ RiscPkg/LibIberty-Dev.inc 20 Feb 2005 20:23:48 -0000 1.1 @@ -0,0 +1,7 @@ +RiscPkg.* +Sprites.!libiberty +SysVars.LibIberty=24Dir +SysVars.LibIberty=24Path +Apps.Library.!LibIberty.!* +Apps.Library.!LibIberty.a.libiberty +Apps.Library.!LibIberty.include.h.* Index: RiscPkg/LibStdC++-Dev.inc =================================================================== RCS file: RiscPkg/LibStdC++-Dev.inc diff -N RiscPkg/LibStdC++-Dev.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ RiscPkg/LibStdC++-Dev.inc 24 Feb 2005 00:33:35 -0000 1.2 @@ -0,0 +1,15 @@ +RiscPkg.* +Sprites.!libstdc++ +SysVars.LibStdCxx=24Dir +SysVars.LibStdCxx=24Path +Apps.Library.!LibStdC++.!Boot +Apps.Library.!LibStdC++.!Run +Apps.Library.!LibStdC++.!Sprites +Apps.Library.!LibStdC++.!Sprites22 +Apps.Library.!LibStdC++.a.libiostream +Apps.Library.!LibStdC++.a.libio +Apps.Library.!LibStdC++.a.libstdc++ +Apps.Library.!LibStdC++.include.* +Apps.Library.!LibStdC++.include.h.* +Apps.Library.!LibStdC++.include.std.h.* +Apps.Library.!LibStdC++.include.std.cc.* Index: RiscPkg/Rules =================================================================== RCS file: RiscPkg/Rules diff -N RiscPkg/Rules --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ RiscPkg/Rules 20 Feb 2005 20:23:48 -0000 1.1 @@ -0,0 +1,139 @@ +GCC_VERSION = 2.95.3-0 +LIBSTDCXX_VERSION = 2.10.0-0 + +GCC_DIR = Apps/Programming/!GCC +BIN_DIR = $(GCC_DIR)/bin +LIB_DIR = $(GCC_DIR)/gcc-lib +TARGET_DIR = $(LIB_DIR)/arm-riscos/2.95.3 +INCLUDE_DIR = $(TARGET_DIR)/include +LIBIBERTY_DIR = Apps/Library/!LibIberty +LIBSTDCXX_DIR = Apps/Library/!LibStdC++ + +PACKAGES = \ + GCC-Common_$(GCC_VERSION) \ + CPP_$(GCC_VERSION) \ + CPP-2.95_$(GCC_VERSION) \ + GCC_$(GCC_VERSION) \ + GCC-2.95_$(GCC_VERSION) \ + G++_$(GCC_VERSION) \ + G++-2.95_$(GCC_VERSION) \ + LibIberty-Dev_$(GCC_VERSION) \ + LibStdC++-Dev_$(LIBSTDCXX_VERSION) + +SPRITES = \ + !GCC/!Sprites \ + !GCC/!Sprites22 \ + !LibIberty/!Sprites \ + !LibIberty/!Sprites22 \ + !LibStdC++/!Sprites \ + !LibStdC++/!Sprites22 + +_GCC_HDRS = iso646.h stdarg.h stdbool.h varargs.h +GCC_HDRS = $(addprefix gcc/ginclude/,$(_GCC_HDRS)) +_GXX_HDRS = exception new typeinfo new.h +GXX_HDRS = $(addprefix gcc/cp/inc/,$(_GXX_HDRS)) +_IO_FILTER = _G_config.h +IO_FILTER = $(addprefix libio/,$(_IO_FILTER))) +IO_HDRS = $(filter-out $(IO_FILTER),$(wildcard libio/*.h)) +_CXX_FILTER = CVS config std stl tests testsuite stage3 \ + %.cc Makefile% configure% ChangeLog NEWS +CXX_FILTER = $(addprefix libstdc++/,$(_CXX_FILTER)) +CXX_HDRS = $(filter-out $(CXX_FILTER),$(wildcard libstdc++/*)) +_STD_FILTER = CVS valarray_array.tcc +STD_FILTER = $(addprefix libstdc++/std/,$(_STD_FILTER)) +STD_HDRS = $(filter-out $(STD_FILTER),$(wildcard libstdc++/std/*)) +_STL_FILTER = CVS README ChangeLog +STL_FILTER = $(addprefix libstdc++/stl/,$(_STL_FILTER)) +STL_HDRS = $(filter-out $(STL_FILTER),$(wildcard libstdc++/stl/*)) + +.PHONY: all +all: uudecode + make -f Makefile.riscpkg + rm -rf Temp + mkdir -p Temp/RiscPkg + mkdir -p Temp/Apps/Programming + cp RiscPkg/Copyright Temp/RiscPkg/ + cp -R !GCC Temp/Apps/Programming/ + mkdir -p Temp/$(BIN_DIR) + cp gcc/stage3/xcpp Temp/$(BIN_DIR)/cpp + cp gcc/stage3/xgcc Temp/$(BIN_DIR)/gcc + cp gcc/stage3/xg++ Temp/$(BIN_DIR)/g++ + mkdir -p Temp/$(TARGET_DIR) + cp gcc/stage3/cpp0 Temp/$(TARGET_DIR)/ + cp gcc/stage3/cc1 Temp/$(TARGET_DIR)/ + cp gcc/stage3/cc1plus Temp/$(TARGET_DIR)/ + cp gcc/stage3/libgcc.a Temp/$(TARGET_DIR)/ + mkdir -p Temp/$(INCLUDE_DIR) + cp $(GCC_HDRS) Temp/$(INCLUDE_DIR)/ + cp $(GXX_HDRS) Temp/$(INCLUDE_DIR)/ + + mkdir -p Temp/$(LIBIBERTY_DIR) + cp -R !LibIberty Temp/Apps/Library + cp libiberty/stage3/libiberty.a Temp/$(LIBIBERTY_DIR) + mkdir -p Temp/$(LIBIBERTY_DIR)/include + cp $(wildcard include/*.h) Temp/$(LIBIBERTY_DIR)/include + + mkdir -p Temp/$(LIBSTDCXX_DIR) + cp -R !LibStdC++ Temp/Apps/Library/ + cp libio/stage3/libiostream.a Temp/$(LIBSTDCXX_DIR) + cp libio/stage3/libio.a Temp/$(LIBSTDCXX_DIR) + cp libstdc++/stage3/libstdc++.a Temp/$(LIBSTDCXX_DIR) + mkdir -p Temp/$(LIBSTDCXX_DIR)/include + cp $(IO_HDRS) Temp/$(LIBSTDCXX_DIR)/include/ + cp $(CXX_HDRS) Temp/$(LIBSTDCXX_DIR)/include/ + cp $(STL_HDRS) Temp/$(LIBSTDCXX_DIR)/include/ + mkdir -p Temp/$(LIBSTDCXX_DIR)/include/std + cp $(STD_HDRS) Temp/$(LIBSTDCXX_DIR)/include/std/ + + chmod -R 444 Temp/Apps + cp -R SysVars Temp/SysVars/ + cp -R Sprites Temp/Sprites/ + mkdir -p Packages + make -C Temp -f ../RiscPkg/Rules $(PACKAGES) + rm -rf Temp + +.PHONY: $(PACKAGES) +$(PACKAGES): %: + riscpkg-gencontrol $(firstword $(subst _, ,$@)) < ../RiscPkg/Control > RiscPkg/Control + rm -f ../Packages/$@ + zip -r ^.Packages.$(subst .,/,$@) * -i@^.RiscPkg.$(subst .,/,$(firstword $(subst _, ,$@)))/inc + +# ---------------------------------------- +# $(uu) == encode +# ---------------------------------------- + +.PHONY: uuencode + +ifeq (encode,$(uu)) + +uuencode: $(addsuffix .uue,$(SPRITES)) + +%.uue: % + uuencode $^,ff9 $^,ff9 > $@ + +else + +uuencode: + make -f RiscPkg/Rules uuencode uu=encode + +endif + +# ---------------------------------------- +# $(uu) == decode +# ---------------------------------------- + +.PHONY: uudecode + +ifeq (decode,$(uu)) + +uudecode: $(SPRITES) + +%: %.uue + uudecode -o $@,ff9 $^ + +else + +uudecode: + make -f RiscPkg/Rules uudecode uu=decode + +endif Index: Sprites/!gcc =================================================================== RCS file: Sprites/!gcc diff -N Sprites/!gcc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Sprites/!gcc 16 Feb 2005 18:24:23 -0000 1.1 @@ -0,0 +1 @@ +.!Sprites \ No newline at end of file Index: Sprites/!libiberty =================================================================== RCS file: Sprites/!libiberty diff -N Sprites/!libiberty --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Sprites/!libiberty 19 Feb 2005 19:44:34 -0000 1.1 @@ -0,0 +1 @@ +.!Sprites \ No newline at end of file Index: Sprites/!libstdc++ =================================================================== RCS file: Sprites/!libstdc++ diff -N Sprites/!libstdc++ --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Sprites/!libstdc++ 16 Feb 2005 18:24:23 -0000 1.1 @@ -0,0 +1 @@ +.!Sprites \ No newline at end of file Index: SysVars/Alias=24cpp =================================================================== RCS file: SysVars/Alias=24cpp diff -N SysVars/Alias=24cpp --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ SysVars/Alias=24cpp 16 Feb 2005 18:24:23 -0000 1.1 @@ -0,0 +1 @@ +/.bin.cpp %*0 \ No newline at end of file Index: SysVars/Alias=24g++ =================================================================== RCS file: SysVars/Alias=24g++ diff -N SysVars/Alias=24g++ --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ SysVars/Alias=24g++ 16 Feb 2005 18:24:23 -0000 1.1 @@ -0,0 +1 @@ +/.bin.g++ %*0 \ No newline at end of file Index: SysVars/Alias=24gcc =================================================================== RCS file: SysVars/Alias=24gcc diff -N SysVars/Alias=24gcc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ SysVars/Alias=24gcc 16 Feb 2005 18:24:23 -0000 1.1 @@ -0,0 +1 @@ +/.bin.gcc %*0 \ No newline at end of file Index: SysVars/GCC=24Dir =================================================================== RCS file: SysVars/GCC=24Dir diff -N SysVars/GCC=24Dir --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ SysVars/GCC=24Dir 16 Feb 2005 18:24:23 -0000 1.1 @@ -0,0 +1 @@ + \ No newline at end of file Index: SysVars/GCC=24Path =================================================================== RCS file: SysVars/GCC=24Path diff -N SysVars/GCC=24Path --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ SysVars/GCC=24Path 16 Feb 2005 18:24:23 -0000 1.1 @@ -0,0 +1 @@ +. \ No newline at end of file Index: SysVars/LibIberty=24Dir =================================================================== RCS file: SysVars/LibIberty=24Dir diff -N SysVars/LibIberty=24Dir --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ SysVars/LibIberty=24Dir 19 Feb 2005 19:52:01 -0000 1.2 @@ -0,0 +1 @@ + \ No newline at end of file Index: SysVars/LibIberty=24Path =================================================================== RCS file: SysVars/LibIberty=24Path diff -N SysVars/LibIberty=24Path --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ SysVars/LibIberty=24Path 19 Feb 2005 19:44:34 -0000 1.1 @@ -0,0 +1 @@ +.,.include. \ No newline at end of file Index: SysVars/LibStdCxx=24Dir =================================================================== RCS file: SysVars/LibStdCxx=24Dir diff -N SysVars/LibStdCxx=24Dir --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ SysVars/LibStdCxx=24Dir 20 Feb 2005 20:21:21 -0000 1.1 @@ -0,0 +1 @@ + \ No newline at end of file Index: SysVars/LibStdCxx=24Path =================================================================== RCS file: SysVars/LibStdCxx=24Path diff -N SysVars/LibStdCxx=24Path --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ SysVars/LibStdCxx=24Path 20 Feb 2005 20:21:21 -0000 1.1 @@ -0,0 +1 @@ +.,.include. \ No newline at end of file Index: gcc/Makefile.riscpkg =================================================================== RCS file: gcc/Makefile.riscpkg diff -N gcc/Makefile.riscpkg --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ gcc/Makefile.riscpkg 20 Feb 2005 20:22:10 -0000 1.3 @@ -0,0 +1,376 @@ +# This file is part of the RISC OS Packaging Project distribution of GCC. +# Copyright © 2005 Graham Shaw. +# Distribution and use are subject to the same terms as GCC as a whole. + +include fixdeps:Rules/make + +topdir=../.. +srcdir=.. + +srcpath = $(srcdir)/autogen:$(srcdir) +vpath %.h $(srcpath) +vpath %.c $(srcpath) +vpath %.cc $(srcpath) +vpath config/% $(srcpath) + +MD = $(srcdir)/config/arm/arm.md +CCFLAGS = -mthrowback -munixlib -mpoke-function-name -O2 +CXXFLAGS = -mthrowback -munixlib -mpoke-function-name -O2 + +# ---------------------------------------- +# $(stage) == autogen +# ---------------------------------------- + +ifeq ($(stage),autogen) + +CPPFLAGS = -I. \ + -I$(srcdir) \ + -I$(topdir)/include \ + -I$(srcdir)/config \ + -DHOST_ARM_RISCOS -DIN_GCC + +ifneq (,$(wildcard /libiberty:/*)) +LIBS = -llibiberty:a.libiberty +else +LIBS = -liberty +endif + +GEN_MD_H = \ + insn-attr.h \ + insn-flags.h \ + insn-codes.h \ + insn-config.h + +GEN_MD_C = \ + insn-attrtab.c \ + insn-emit.c \ + insn-output.c \ + insn-recog.c \ + insn-extract.c \ + insn-peep.c \ + insn-opinit.c + +GEN_MD := $(GEN_MD_H) $(GEN_MD_C) + +GEN_MD_BIN := \ + $(patsubst insn-%.h,gen%,$(GEN_MD_H)) \ + $(patsubst insn-%.c,gen%,$(GEN_MD_C)) + +GEN_ALL = \ + $(GEN_MD) \ + tree.h \ + genrtl.h + +.PHONY: all +all: $(GEN_ALL) tconfig.h + +OBJ_BIN = rtl.o bitmap.o +EXTRA_OBJ_genattrtab = rtlanal.o +EXTRA_OBJ_genrecog = print-rtl.o +ALL_OBJ_BIN = $(OBJ_BIN) rtlanal.o print-rtl.o + +$(GEN_MD_BIN): %: %.o $(ALL_OBJ_BIN) + $(LD) -o $@ $< $(OBJ_BIN) $(EXTRA_OBJ_$@) $(LIBS) + +$(GEN_MD_BIN:=.o): hconfig.h genrtl.h + +$(GEN_MD_H): insn-%.h: $(MD) gen% + ./gen$* $(MD) > insn-$*.h +$(GEN_MD_C): insn-%.c: $(MD) gen% + ./gen$* $(MD) > insn-$*.c + +hconfig.h: config.h + cp $< $@ + +tconfig.h: config.h + cp $< $@ + +genrtl.h gentrl.c: gengenrtl + ./gengenrtl genrtl.h genrtl.c + +tree.h: tree-check.h +tree-check.h: gencheck + ./gencheck > tree-check.h + +endif + +# ---------------------------------------- +# $(stage) == stage1, stage2 or stage3 +# ---------------------------------------- + +ifneq (,$(findstring stage,$(stage))) + +LD = drlink -rescan + +ifeq (stage1,$(stage)) +LIBS = unixlib:unixlib.a \ + $(topdir)/libiberty/stage1/libiberty.a +endif + +ifeq (stage2,$(stage)) +CC = $(srcdir)/stage1/xgcc -B$(srcdir)/stage1/ +CXX = $(CC) +LIBS = unixlib:unixlib.a \ + $(topdir)/libiberty/stage2/libiberty.a +endif + +ifeq (stage3,$(stage)) +CC = $(srcdir)/stage2/xgcc -B$(srcdir)/stage2/ +CXX = $(CC) +LIBS = unixlib:unixlib.a \ + $(topdir)/libiberty/stage3/libiberty.a +endif + +TARGET_NAME = arm-riscos +VERSION = 2.95.3 + +TARGET_PATH = /gcc:/gcc-lib/$(TARGET_NAME)/$(VERSION) +GCC_INCLUDE_DIR = $(TARGET_PATH)/include +GXX_INCLUDE_DIR = /libstdcxx:/include +SYSTEM_INCLUDE_DIR = /unixlib:/include + +CPPFLAGS = \ + -nostdinc \ + -I/unixlib: \ + -I$(topdir)/gcc/ginclude \ + -I$(topdir)/gcc/cp/inc \ + -I$(topdir)/include \ + -I$(srcdir)/autogen \ + -I$(srcdir) \ + -I$(srcdir)/config \ + -DTARGET_RISCOSAOF \ + -DHOST_ARM_RISCOS \ + -DHAVE_CONFIG_H \ + -DIN_GCC \ + -DDEFAULT_TARGET_VERSION=\"$(VERSION)\" \ + -DDEFAULT_TARGET_MACHINE=\"$(TARGET_NAME)\" \ + -DTARGET_NAME=\"$(TARGET_NAME)\" \ + -DPREFIX=\"/nowhere/\" \ + -DSTANDARD_EXEC_PREFIX=\"/gcc-lib/\" \ + -DGCC_INCLUDE_DIR=\"$(GCC_INCLUDE_DIR)\" \ + -DGXX_INCLUDE_DIR=\"$(GXX_INCLUDE_DIR)\" \ + -DSYSTEM_INCLUDE_DIR=\"$(SYSTEM_INCLUDE_DIR)\" \ + -DDONT_USE_BUILTIN_SETJMP \ + -DJMP_BUF_SIZE=27 + + +GCC_OBJS = \ + gcc.o \ + gccspec.o \ + prefix.o \ + version.o + +CPP_OBJS = \ + cccp.o \ + cexp.o \ + prefix.o \ + version.o + +CPP0_OBJS = \ + cppmain.o \ + cpplib.o \ + cpphash.o \ + cppalloc.o \ + cpperror.o \ + cppexp.o \ + cppfiles.o \ + cppinit.o \ + cppulp.o \ + prefix.o \ + version.o + +RISCOS_OBJS = \ + config/arm/riscos.o \ + config/arm/arm.o + +# Language-specific object files for C and Objective C. +C_AND_OBJC_OBJS = c-lex.o c-pragma.o c-decl.o c-typeck.o c-convert.o \ + c-aux-info.o c-common.o c-iterate.o + +# Language-specific object files for C. +C_OBJS = c-parse.o c-lang.o $(C_AND_OBJC_OBJS) + +# Language-independent object files. +OBJS = toplev.o version.o tree.o print-tree.o stor-layout.o fold-const.o \ + function.o stmt.o except.o expr.o calls.o expmed.o explow.o optabs.o \ + varasm.o rtl.o print-rtl.o rtlanal.o emit-rtl.o genrtl.o real.o \ + dbxout.o sdbout.o dwarfout.o dwarf2out.o xcoffout.o bitmap.o alias.o gcse.o \ + integrate.o jump.o cse.o loop.o unroll.o flow.o stupid.o combine.o varray.o \ + regclass.o regmove.o local-alloc.o global.o reload.o reload1.o caller-save.o \ + insn-peep.o reorg.o $(SCHED_PREFIX)sched.o final.o recog.o reg-stack.o \ + insn-opinit.o insn-recog.o insn-extract.o insn-output.o insn-emit.o lcm.o \ + profile.o insn-attrtab.o $(out_object_file) getpwd.o $(EXTRA_OBJS) convert.o \ + dyn-string.o graph.o sbitmap.o resource.o hash.o + +LIBGCC2_OBJS = \ + _main.o \ + _gcc_bcmp.o \ + _dummy.o \ + eh.o \ + eprintf.o \ + pure.o \ + bb.o \ + +LIB1AOF_OBJS = \ + div0.o \ + arm_alloca.o \ + clear_icache.o \ + ctors.o \ + cmpdi2.o \ + ucmpdi2.o \ + modsi3.o \ + umodsi3.o \ + divsi3.o \ + udivsi3.o \ + moddi3.o \ + umoddi3.o \ + divdi3.o \ + udivdi3.o \ + floatdidf.o \ + fixunsxfdi.o \ + fixunsdfdi.o \ + fixunssfdi.o \ + fixsfdi.o \ + ffs.o \ + ashldi3.o \ + ashrdi3.o \ + lshrdi3.o \ + muldi3.o \ + builtin_next_arg.o \ + +FP_BIT_DOUBLE = \ + pack_df.o \ + unpack_df.o \ + addsub_df.o \ + mul_df.o \ + div_df.o \ + fpcmp_parts_df.o \ + compare_df.o \ + eq_df.o \ + ne_df.o \ + gt_df.o \ + ge_df.o \ + lt_df.o \ + le_df.o \ + si_to_df.o \ + df_to_si.o \ + df_to_usi.o \ + negate_df.o \ + make_df.o \ + df_to_sf.o + +FP_BIT_SINGLE = \ + pack_sf.o \ + unpack_sf.o \ + addsub_sf.o \ + mul_sf.o \ + div_sf.o \ + fpcmp_parts_sf.o \ + compare_sf.o \ + eq_sf.o \ + ne_sf.o \ + gt_sf.o \ + ge_sf.o \ + lt_sf.o \ + le_sf.o \ + si_to_sf.o \ + sf_to_usi.o \ + sf_to_si.o \ + negate_sf.o \ + make_sf.o \ + sf_to_df.o + +NEW1_OBJS = \ + cp/op_new.o \ + cp/op_newnt.o + +NEW2_OBJS = \ + cp/op_vnew.o \ + cp/op_vnewnt.o \ + cp/op_delete.o \ + cp/op_delnt.o \ + cp/op_vdel.o \ + cp/op_vdelnt.o + +ifeq (stage3,$(stage)) +LIBGPP_OBJS = \ + $(NEW1_OBJS) \ + $(NEW2_OBJS) \ + cp/tinfo.o \ + cp/tinfo2.o \ + cp/new.o \ + cp/exception.o +endif + +LIBGCC_OBJS = \ + $(LIBGCC2_OBJS) \ + $(LIB1AOF_OBJS) \ + $(FP_BIT_DOUBLE) \ + $(FP_BIT_SINGLE) \ + libgcc_fix.o + +ifeq (stage1,$(stage)) +all: xgcc cpp0 cc1 libgcc.a +else +ifeq (stage2,$(stage)) +all: xgcc cpp0 cc1 cc1plus libgcc.a +else +all: xcpp xgcc xg++ cpp0 cc1 cc1plus libgcc.a +endif +endif + +xcpp: $(CPP_OBJS) libgcc.a + $(LD) -o $@ $^ $(LIBS) + +xgcc: $(GCC_OBJS) libgcc.a + $(LD) -o $@ $^ $(LIBS) + +cpp0: $(CPP0_OBJS) libgcc.a + $(LD) -o $@ $^ $(LIBS) + +cc1: $(C_OBJS) $(OBJS) $(RISCOS_OBJS) libgcc.a + $(LD) -o $@ $^ $(LIBS) + +libgcc.a: $(LIBGCC_OBJS) $(LIBGPP_OBJS) + mkdir -p a + $(AR) -c a.libgcc $(LIBGCC_OBJS:%.o=o.%) + $(AR) -r a.libgcc $(LIBGPP_OBJS:cp/%.o=cp.o.%) + +$(LIBGCC2_OBJS): %.o: libgcc2.c + $(CC) -c $(CCFLAGS) $(CPPFLAGS) -o $@ $< -DL_$* + +$(LIB1AOF_OBJS): %.o: config/arm/lib1aof.s + $(CC) -c -xassembler-with-cpp $(CPPFLAGS) -o $@ $< -DL_$* + +FPBIT_DEFS_D = -DFINE_GRAINED_LIBRARIES +$(FP_BIT_DOUBLE): %.o: config/fp-bit.c + $(CC) -c $(CCFLAGS) $(CPPFLAGS) -o $@ $< -DL_$* $(FPBIT_DEFS_D) + +FPBIT_DEFS_S = -DFINE_GRAINED_LIBRARIES -DFLOAT +$(FP_BIT_SINGLE): %.o: config/fp-bit.c + $(CC) -c $(CCFLAGS) $(CPPFLAGS) -o $@ $< -DL_$* $(FPBIT_DEFS_S) + +$(NEW1_OBJS): cp/%.o: cp/new1.cc + $(CXX) -c $(CXXFLAGS) $(CPPFLAGS) -o $@ $< -DL_$* + +$(NEW2_OBJS): cp/%.o: cp/new2.cc + $(CXX) -c $(CXXFLAGS) $(CPPFLAGS) -o $@ $< -DL_$* + +libgcc_fix.o: config/arm/libgcc_fix.s + $(CC) -c -xassembler-with-cpp $(CPPFLAGS) -o $@ $< + +include $(srcdir)/cp/Makefile.riscpkg + +include $(CPP_OBJS:.o=.d) +include $(GCC_OBJS:.o=.d) +include $(CPP0_OBJS:.o=.d) +include $(RISCOS_OBJS:.o=.d) +include $(C_OBJS:.o=.d) +include $(OBJS:.o=.d) +include libgcc2.d + +endif + +dirs: + mkdir -p config/arm + mkdir -p cp Index: gcc/config.h =================================================================== RCS file: gcc/config.h diff -N gcc/config.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ gcc/config.h 9 Feb 2005 06:23:01 -0000 1.1 @@ -0,0 +1,372 @@ +/* config.h. Hand-edited from config.in by Graham Shaw to match + * features provided by GCC and UnixLib. */ + +/* Define if you can safely include both and . */ +#define STRING_WITH_STRINGS 1 + +/* Define if printf supports "%p". */ +#define HAVE_PRINTF_PTR 1 + +/* Define if you want expensive run-time checks. */ +#undef ENABLE_CHECKING + +/* Define to 1 if NLS is requested. */ +#undef ENABLE_NLS + +/* Define as 1 if you have catgets and don't want to use GNU gettext. */ +#undef HAVE_CATGETS + +/* Define as 1 if you have gettext and don't want to use GNU gettext. */ +#undef HAVE_GETTEXT + +/* Define if your cpp understands the stringify operator. */ +#define HAVE_CPP_STRINGIFY 1 + +/* Define if your compiler understands volatile. */ +#define HAVE_VOLATILE 1 + +/* Define if your assembler supports specifying the maximum number + of bytes to skip when using the GAS .p2align command. */ +#undef HAVE_GAS_MAX_SKIP_P2ALIGN + +/* Define if your assembler supports .balign and .p2align. */ +#undef HAVE_GAS_BALIGN_AND_P2ALIGN + +/* Define if your assembler supports .subsection and .subsection -1 starts + emitting at the beginning of your section */ +#undef HAVE_GAS_SUBSECTION_ORDERING + +/* Define if your assembler uses the old HImode fild and fist notation. */ +#undef HAVE_GAS_FILDS_FISTS + +/* Define if you have a working header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define if your locale.h file contains LC_MESSAGES. */ +#define HAVE_LC_MESSAGES 1 + +/* Define as 1 if you have the stpcpy function. */ +#define HAVE_STPCPY 1 + +/* Whether malloc must be declared even if is included. */ +#undef NEED_DECLARATION_MALLOC + +/* Whether realloc must be declared even if is included. */ +#undef NEED_DECLARATION_REALLOC + +/* Whether calloc must be declared even if is included. */ +#undef NEED_DECLARATION_CALLOC + +/* Whether free must be declared even if is included. */ +#undef NEED_DECLARATION_FREE + +/* Whether bcopy must be declared even if is included. */ +#undef NEED_DECLARATION_BCOPY + +/* Whether bcmp must be declared even if is included. */ +#undef NEED_DECLARATION_BCMP + +/* Whether bzero must be declared even if is included. */ +#undef NEED_DECLARATION_BZERO + +/* Whether index must be declared even if is included. */ +#undef NEED_DECLARATION_INDEX + +/* Whether rindex must be declared even if is included. */ +#undef NEED_DECLARATION_RINDEX + +/* Whether getenv must be declared even if is included. */ +#undef NEED_DECLARATION_GETENV + +/* Whether atol must be declared even if is included. */ +#undef NEED_DECLARATION_ATOL + +/* Whether atof must be declared even if is included. */ +#undef NEED_DECLARATION_ATOF + +/* Whether sbrk must be declared even if is included. */ +#undef NEED_DECLARATION_SBRK + +/* Whether abort must be declared even if is included. */ +#undef NEED_DECLARATION_ABORT + +/* Whether strerror must be declared even if is included. */ +#undef NEED_DECLARATION_STRERROR + +/* Whether strsignal must be declared even if is included. */ +#undef NEED_DECLARATION_STRSIGNAL + +/* Whether strstr must be declared even if is included. */ +#undef NEED_DECLARATION_STRSTR + +/* Whether getcwd must be declared even if is included. */ +#undef NEED_DECLARATION_GETCWD + +/* Whether getwd must be declared even if is included. */ +#undef NEED_DECLARATION_GETWD + +/* Whether getrlimit must be declared even if is included. */ +#undef NEED_DECLARATION_GETRLIMIT + +/* Whether setrlimit must be declared even if is included. */ +#undef NEED_DECLARATION_SETRLIMIT + +/* Whether putc_unlocked must be declared even if is included. */ +#undef NEED_DECLARATION_PUTC_UNLOCKED + +/* Whether fputs_unlocked must be declared even if is included. */ +#undef NEED_DECLARATION_FPUTS_UNLOCKED + +/* Define to enable the use of a default assembler. */ +#undef DEFAULT_ASSEMBLER + +/* Define to enable the use of a default linker. */ +#undef DEFAULT_LINKER + +/* Define if host mkdir takes a single argument. */ +#undef MKDIR_TAKES_ONE_ARG + +/* Define to the name of the distribution. */ +#define PACKAGE "gcc" + +/* Define to the version of the distribution. */ +#define VERSION "2.95.3" + +/* Define if using alloca.c. */ +#undef C_ALLOCA + +/* Define to empty if the keyword does not work. */ +#undef const + +/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. + This function is required for alloca.c support on those systems. */ +#undef CRAY_STACKSEG_END + +/* Define if you have alloca, as a function or macro. */ +#define HAVE_ALLOCA 1 + +/* Define if you have and it should be used (not on Ultrix). */ +#define HAVE_ALLOCA_H 1 + +/* Define if you don't have vprintf but do have _doprnt. */ +#undef HAVE_DOPRNT + +/* Define if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define if you have that is POSIX.1 compatible. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define if you have . */ +#undef HAVE_VFORK_H + +/* Define if you have the vprintf function. */ +#define HAVE_VPRINTF 1 + +/* Define as __inline if that's what the C compiler calls it. */ +#undef inline + +/* Define to `long' if doesn't define. */ +#undef off_t + +/* Define to `int' if doesn't define. */ +#undef pid_t + +/* Define to `unsigned' if doesn't define. */ +#undef size_t + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown + */ +#undef STACK_DIRECTION + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if `sys_siglist' is declared by . */ +#define SYS_SIGLIST_DECLARED 1 + +/* Define if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define vfork as fork if vfork does not work. */ +#undef vfork + +/* Define if you have the __argz_count function. */ +#undef HAVE___ARGZ_COUNT + +/* Define if you have the __argz_next function. */ +#undef HAVE___ARGZ_NEXT + +/* Define if you have the __argz_stringify function. */ +#undef HAVE___ARGZ_STRINGIFY + +/* Define if you have the atoll function. */ +#define HAVE_ATOLL 1 + +/* Define if you have the atoq function. */ +#undef HAVE_ATOQ + +/* Define if you have the bcmp function. */ +#define HAVE_BCMP 1 + +/* Define if you have the bcopy function. */ +#define HAVE_BCOPY 1 + +/* Define if you have the bsearch function. */ +#define HAVE_BSEARCH 1 + +/* Define if you have the bzero function. */ +#define HAVE_BZERO 1 + +/* Define if you have the dcgettext function. */ +#undef HAVE_DCGETTEXT + +/* Define if you have the fputc_unlocked function. */ +#undef HAVE_FPUTC_UNLOCKED + +/* Define if you have the fputs_unlocked function. */ +#undef HAVE_FPUTS_UNLOCKED + +/* Define if you have the getcwd function. */ +#define HAVE_GETCWD 1 + +/* Define if you have the getpagesize function. */ +#define HAVE_GETPAGESIZE 1 + +/* Define if you have the getrlimit function. */ +#define HAVE_GETRLIMIT 1 + +/* Define if you have the gettimeofday function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define if you have the index function. */ +#define HAVE_INDEX 1 + +/* Define if you have the isascii function. */ +#define HAVE_ISASCII 1 + +/* Define if you have the kill function. */ +#define HAVE_KILL 1 + +/* Define if you have the munmap function. */ +#undef HAVE_MUNMAP + +/* Define if you have the popen function. */ +#define HAVE_POPEN 1 + +/* Define if you have the putc_unlocked function. */ +#undef HAVE_PUTC_UNLOCKED + +/* Define if you have the putenv function. */ +#define HAVE_PUTENV 1 + +/* Define if you have the rindex function. */ +#define HAVE_RINDEX 1 + +/* Define if you have the setenv function. */ +#define HAVE_SETENV 1 + +/* Define if you have the setlocale function. */ +#define HAVE_SETLOCALE 1 + +/* Define if you have the setrlimit function. */ +#define HAVE_SETRLIMIT 1 + +/* Define if you have the stpcpy function. */ +#define HAVE_STPCPY 1 + +/* Define if you have the strcasecmp function. */ +#define HAVE_STRCASECMP 1 + +/* Define if you have the strchr function. */ +#define HAVE_STRCHR 1 + +/* Define if you have the strdup function. */ +#define HAVE_STRDUP 1 + +/* Define if you have the strerror function. */ +#define HAVE_STRERROR 1 + +/* Define if you have the strrchr function. */ +#define HAVE_STRRCHR 1 + +/* Define if you have the strsignal function. */ +#define HAVE_STRSIGNAL 1 + +/* Define if you have the strtoul function. */ +#define HAVE_STRTOUL 1 + +/* Define if you have the sysconf function. */ +#define HAVE_SYSCONF 1 + +/* Define if you have the header file. */ +#undef HAVE_ARGZ_H + +/* Define if you have the header file. */ +#undef HAVE_DIRECT_H + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define if you have the header file. */ +#define HAVE_MALLOC_H 1 + +/* Define if you have the header file. */ +#undef HAVE_NL_TYPES_H + +/* Define if you have the header file. */ +#undef HAVE_STAB_H + +/* Define if you have the header file. */ +#define HAVE_STDDEF_H 1 + +/* Define if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_FILE_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_TIMES_H 1 + +/* Define if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define if you have the i library (-li). */ +#undef HAVE_LIBI + +#include "gansidecl.h" +#include "config/arm/xm-riscos.h" +#include "hwint.h" Index: gcc/except.c =================================================================== RCS file: /var/cvs/GCC-2.95/gcc/except.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- gcc/except.c 7 Feb 2005 22:50:17 -0000 1.1.1.1 +++ gcc/except.c 24 Feb 2005 00:48:06 -0000 1.2 @@ -1343,7 +1343,7 @@ but there is no allocation routine that allocates at the level of the last binding contour. */ arg = assign_stack_local (BLKmode, - GET_MODE_SIZE (Pmode)*(size+1), + GET_MODE_SIZE (Pmode)*(size+2), 0); arg = change_address (arg, Pmode, NULL_RTX); Index: gcc/expr.c =================================================================== RCS file: /var/cvs/GCC-2.95/gcc/expr.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- gcc/expr.c 7 Feb 2005 22:50:17 -0000 1.1.1.1 +++ gcc/expr.c 8 Feb 2005 01:20:33 -0000 1.2 @@ -8516,6 +8516,36 @@ count--; #endif +#if defined(HAVE_BUILTIN_RETURN_ADDR_FUNC) || defined(HAVE_BUILTIN_FRAME_ADDR_FUNC) + { + char *func = NULL; + + /* If HAVE_BUILTIN_RETURN_ADDR_FUNC or HAVE_BUILTIN_FRAME_ADDR_FUNC + are defined, and evaluate to something, then call + __builtin_return_address as a function. */ +#ifdef HAVE_BUILTIN_RETURN_ADDR_FUNC + if (fndecl_code == BUILT_IN_RETURN_ADDRESS + && HAVE_BUILTIN_RETURN_ADDR_FUNC) + func = "__builtin_return_address"; +#endif +#ifdef HAVE_BUILTIN_FRAME_ADDR_FUNC + if (fndecl_code == BUILT_IN_FRAME_ADDRESS + && HAVE_BUILTIN_FRAME_ADDR_FUNC) + func = "__builtin_frame_address"; +#endif + + if (func != NULL) + { + rtx function_call; + + tem = gen_reg_rtx (Pmode); + function_call = gen_rtx (SYMBOL_REF, Pmode, func); + emit_library_call_value (function_call, tem, 0, Pmode, 1, + GEN_INT (count), SImode); + } + } +#endif + /* Scan back COUNT frames to the specified frame. */ for (i = 0; i < count; i++) { Index: gcc/gencheck.h =================================================================== RCS file: gcc/gencheck.h diff -N gcc/gencheck.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ gcc/gencheck.h 15 Feb 2005 16:44:55 -0000 1.3 @@ -0,0 +1 @@ +#include "cp/cp-tree.def" Index: gcc/global.c =================================================================== RCS file: /var/cvs/GCC-2.95/gcc/global.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- gcc/global.c 7 Feb 2005 22:50:17 -0000 1.1.1.1 +++ gcc/global.c 8 Feb 2005 01:20:33 -0000 1.2 @@ -291,7 +291,12 @@ int need_fp = (! flag_omit_frame_pointer #ifdef EXIT_IGNORE_STACK +#ifdef PREVENT_FP_CLOBBER + || (current_function_calls_alloca && EXIT_IGNORE_STACK + && ! PREVENT_FP_CLOBBER) +#else || (current_function_calls_alloca && EXIT_IGNORE_STACK) +#endif #endif || FRAME_POINTER_REQUIRED); Index: gcc/multilib.h =================================================================== RCS file: gcc/multilib.h diff -N gcc/multilib.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ gcc/multilib.h 9 Feb 2005 06:23:01 -0000 1.1 @@ -0,0 +1,35 @@ +/* Multilib support for ARM/RISC OS. + Written by Nick Burrett 255L) width = 255L; /* arbitrary */ sprintf (fmt, "%%.%lds", width); fprintf (stderr, fmt, _(msgid)); +#ifdef ERROR_THROWBACK + sprintf (msg, fmt, _(msgid)); +#endif } if (*p == '%') /* Print the name. */ @@ -1736,6 +1747,9 @@ ? (*decl_printable_name) (decl, 2) : "((anonymous))"); fputs (n, stderr); +#ifdef ERROR_THROWBACK + strcat (msg, n); +#endif while (*p) { ++p; @@ -1745,9 +1759,20 @@ } if (*p) /* Print the rest of the message. */ - vmessage ((char *)NULL, p, ap); - + { +#ifdef ERROR_THROWBACK + char tmp[256]; + + vsprintf (tmp, p, ap); + strcat (msg, tmp); +#endif + vmessage ((char *)NULL, p, ap); + } fputc ('\n', stderr); +#ifdef ERROR_THROWBACK + ERROR_THROWBACK (DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl), + (warn) ? "warning" : NULL, msg, 0); +#endif } /* Figure file and line of the given INSN. */ @@ -5447,7 +5472,15 @@ print_switch_values (stderr, 0, MAX_LINE, "", " ", "\n"); } +#ifdef ERROR_THROWBACK_INITIALISE + ERROR_THROWBACK_INITIALISE; +#endif + compile_file (filename); + +#ifdef ERROR_THROWBACK_FINALISE + ERROR_THROWBACK_FINALISE; +#endif #if !defined(OS2) && !defined(VMS) && (!defined(_WIN32) || defined (__CYGWIN__)) && !defined(__INTERIX) if (flag_print_mem) Index: gcc/varasm.c =================================================================== RCS file: /var/cvs/GCC-2.95/gcc/varasm.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- gcc/varasm.c 7 Feb 2005 22:50:19 -0000 1.1.1.1 +++ gcc/varasm.c 15 Feb 2005 14:34:29 -0000 1.2 @@ -1694,7 +1694,15 @@ TREE_SYMBOL_REFERENCED (id) = 1; if (name[0] == '*') + { +#if defined(TARGET_RISCOSAOF) + /* A quick hack for C++ RTTI until I've fixed the relevant bug. */ + if (name[1] != '|') + fprintf (file, "|%s|", &name[1]); + else +#endif fputs (&name[1], file); + } else ASM_OUTPUT_LABELREF (file, name); } Index: gcc/config/arm/arm.c =================================================================== RCS file: /var/cvs/GCC-2.95/gcc/config/arm/arm.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- gcc/config/arm/arm.c 7 Feb 2005 22:50:22 -0000 1.1.1.1 +++ gcc/config/arm/arm.c 8 Feb 2005 01:20:33 -0000 1.2 @@ -70,6 +70,8 @@ static void emit_sfm PROTO ((int, int)); static enum arm_cond_code get_arm_condition_code PROTO ((rtx)); static int const_ok_for_op RTX_CODE_PROTO ((HOST_WIDE_INT, Rcode)); +static int arm_leaf_function_p PROTO ((void)); +static int arm_stack_check_needed PROTO ((void)); /* True if we are currently building a constant table. */ int making_const_table; @@ -148,6 +150,10 @@ but all of these can be `put after' return insns */ int lr_save_eliminated; +/* Set to one if the current function is a leaf function. Set to zero if + it isn't. Set to -1 if the function type hasn't been decided. */ +static int arm_leaf_function = -1; + /* Set to 1 when a return insn is output, this means that the epilogue is not needed. */ static int return_used_this_function; @@ -295,7 +301,7 @@ a warning though, and we prefer the CPU over the architecture. */ if (insn_flags != 0 && (insn_flags ^ sel->flags)) - warning ("switch -mcpu=%s conflicts with -mtune= switch", + warning ("switch -mcpu=%s conflicts with -march= switch", ptr->string); insn_flags = sel->flags; @@ -566,8 +572,9 @@ if (!reload_completed || current_function_pretend_args_size || current_function_anonymous_args - || ((get_frame_size () + current_function_outgoing_args_size != 0) - && !(TARGET_APCS && frame_pointer_needed))) + || (current_function_calls_alloca && ! TARGET_APCS) + || (current_function_outgoing_args_size && ! TARGET_APCS) + || (get_frame_size () && ! arm_apcs_frame_needed ())) return 0; /* Can't be done if interworking with Thumb, and any registers have been @@ -4059,6 +4066,8 @@ break; default: + fprintf (stderr, "dump_table: size = %d\n", + GET_MODE_SIZE (p->mode)); abort (); break; } @@ -4381,16 +4390,18 @@ must follow the register list. */ void -print_multi_reg (stream, instr, mask, hat) - FILE *stream; - char *instr; - int mask, hat; +print_multi_reg (stream, instr, base_reg, mask, hat, write_back) + FILE * stream; + char * instr; + int base_reg, mask, hat, write_back; { int i; int not_first = FALSE; - fputc ('\t', stream); - fprintf (stream, instr, REGISTER_PREFIX); + fprintf (stream, "\t%s\t%s%s", instr, REGISTER_PREFIX, reg_names[base_reg]); + + if (write_back) + fputc ('!', stream); fputs (", {", stream); for (i = 0; i < 16; i++) if (mask & (1 << i)) @@ -5135,6 +5146,15 @@ fputs ("\"\n", stream); } +/* Return non-zero if this is a leaf function. */ +static int +arm_leaf_function_p () +{ + if (arm_leaf_function < 0) + arm_leaf_function = leaf_function_p (); + + return arm_leaf_function; +} /* Try to determine whether a pattern really clobbers the link register. This information is useful when peepholing, so that lr need not be pushed @@ -5260,7 +5280,8 @@ if (GET_CODE (next) == BARRIER) break; - if (GET_CODE (next) == INSN && GET_CODE (PATTERN (next)) == USE + /* There can be multiple USE statements. */ + while (GET_CODE (next) == INSN && GET_CODE (PATTERN (next)) == USE && (GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET) && (REGNO (SET_DEST (XVECEXP (PATTERN (insn), 0, 0))) == REGNO (XEXP (PATTERN (next), 0)))) @@ -5288,13 +5309,14 @@ int reverse; { char instr[100]; - int reg, live_regs = 0; + int reg, live_regs_mask = 0; int volatile_func = (optimize > 0 && TREE_THIS_VOLATILE (current_function_decl)); + int frame_needed; return_used_this_function = 1; - if (volatile_func) + if (TARGET_ABORT_NORETURN && volatile_func) { rtx ops[2]; /* If this function was declared non-returning, and we have found a tail @@ -5313,63 +5335,51 @@ if (current_function_calls_alloca && ! really_return) abort(); - - for (reg = 0; reg <= 10; reg++) - if (regs_ever_live[reg] && ! call_used_regs[reg]) - live_regs++; if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM]) - live_regs++; + live_regs_mask |= 1 << PIC_OFFSET_TABLE_REGNUM; - if (live_regs || (regs_ever_live[14] && ! lr_save_eliminated)) - live_regs++; - - if (frame_pointer_needed) - live_regs += 4; + frame_needed = arm_apcs_frame_needed (); + if (frame_needed) + { + for (reg = 0; reg <= 10; reg ++) + if (regs_ever_live[reg] && ! call_used_regs[reg]) + live_regs_mask |= 1 << reg; - if (live_regs) + /* If we are really returning then restore regs pc, sp and fp + otherwise restore fp, sp and lr. */ + if (! lr_save_eliminated) + live_regs_mask |= really_return ? 0xa800 : 0x6800; + } + else { - if (lr_save_eliminated || ! regs_ever_live[14]) - live_regs++; + for (reg = 0; reg <= 12; reg ++) + if (regs_ever_live[reg] && ! call_used_regs[reg]) + live_regs_mask |= 1 << reg; - if (frame_pointer_needed) - strcpy (instr, + if (live_regs_mask + || (regs_ever_live[14] && ! lr_save_eliminated)) + live_regs_mask |= 1 << (really_return ? 15 : 14); + } + + if (live_regs_mask) + { + if (frame_needed) + strcpy (instr, reverse ? "ldm%?%D0ea\t%|fp, {" : "ldm%?%d0ea\t%|fp, {"); else strcpy (instr, reverse ? "ldm%?%D0fd\t%|sp!, {" : "ldm%?%d0fd\t%|sp!, {"); - for (reg = 0; reg <= 10; reg++) - if (regs_ever_live[reg] - && (! call_used_regs[reg] - || (flag_pic && reg == PIC_OFFSET_TABLE_REGNUM))) - { + for (reg = 0; live_regs_mask; reg ++, live_regs_mask >>= 1) + if (live_regs_mask & 1) + { strcat (instr, "%|"); - strcat (instr, reg_names[reg]); - if (--live_regs) - strcat (instr, ", "); - } + strcat (instr, reg_names[reg]); + if (live_regs_mask >> 1) + strcat (instr, ", "); + } - if (frame_pointer_needed) - { - strcat (instr, "%|"); - strcat (instr, reg_names[11]); - strcat (instr, ", "); - strcat (instr, "%|"); - strcat (instr, reg_names[13]); - strcat (instr, ", "); - strcat (instr, "%|"); - strcat (instr, TARGET_THUMB_INTERWORK || (! really_return) - ? reg_names[14] : reg_names[15] ); - } - else - { - strcat (instr, "%|"); - if (TARGET_THUMB_INTERWORK && really_return) - strcat (instr, reg_names[12]); - else - strcat (instr, really_return ? reg_names[15] : reg_names[14]); - } strcat (instr, (TARGET_APCS_32 || !really_return) ? "}" : "}^"); output_asm_insn (instr, &operand); @@ -5454,24 +5464,114 @@ ASM_OUTPUT_INT (stream, x); } -/* The amount of stack adjustment that happens here, in output_return and in - output_epilogue must be exactly the same as was calculated during reload, - or things will point to the wrong place. The only time we can safely - ignore this constraint is when a function has no arguments on the stack, - no stack frame requirement and no live registers execpt for `lr'. If we - can guarantee that by making all function calls into tail calls and that - lr is not clobbered in any other way, then there is no need to push lr - onto the stack. */ - +/* Obtain the last bit set. */ + +static HOST_WIDE_INT +last_bit_set (value) + HOST_WIDE_INT value; +{ + HOST_WIDE_INT shift = 31; + + while (((1 << shift) & value) == 0) + { + if (shift < 0) + abort (); + shift--; + } + + return shift; +} + +/* Front end to output_add_immediate. */ + +static void +output_add_imm (reg1, reg2, imm) + int reg1, reg2, imm; +{ + rtx operands[3]; + + operands[0] = gen_rtx (REG, SImode, reg1); + operands[1] = gen_rtx (REG, SImode, reg2); + operands[2] = GEN_INT (imm); + output_add_immediate (operands); +} + +/* Output the full function prologue, in accordance with the ARM + Procedure Call Standard (APCS). + + There are currently 16 APCS variants, divided into four categories. + a) 26-bit program counter (PC) or 32-bit PC. + b) Implicit or explicit stack limit checking + c) Pass floating point registers on the stack or in FP args + d) Reentrant and non-reentrant + + Variants (c) and (d) are currently not implemented. + + The following example shows what the entry and exit sequences for a + function are likely to look like + entry: + mov ip, sp + stmfd sp!, {arg_regs, work_regs, fp, ip, lr, pc} + sub fp, ip, #4 + + exit: + ldmea fp, {work_regs, fp, sp, pc}^ + + For variadic functions, we make a contiguous argument list by using + a slightly modified entry sequence: + mov ip, sp + stmfd sp!, {a1, a2, a3, a4} + stmfd sp!, {work_regs, fp, ip, lr, pc} + sub fp, ip, #4 + + If we enable stack limit checking, the entry sequence for a + non-variadic function becomes: + mov ip, sp + stmfd sp!, {arg_regs, work_regs, fp, ip, lr, pc} + sub fp, ip, #4 + cmp sp, sl + bllt |__rt_stkovf_split_small| + sub sp, sp, # + + + The check for stack limit violation is made at the end of the function + prologue, by which time ip is available as a work register. If the + stack check fails, one of two standard run-time functions are called. + These functions will either + a) terminate the application + b) extend the existing stack check (decrementing sl) + c) allocate a new stack chunk, altering sp and sl + to point to it. + + For functions that are going to use less than 256 bytes of stack: + cmp sp, sl + bllt |__rt_stkovf_split_small| + sub sp, sp, # + + After this call, fp and sp might point to different stack chunks. + + For functions that are going to use more than 256 bytes of stack: + sub ip, sp, # + cmp ip, sl + bllt |__arm_stkovf_split_big| + sub sp, sp, # + + After this call, fp and sp might point to different stack chunks. + + The above describes the basic layout of an APCS prologue. However, it + is not always necessary to conform to this exact style. Often the + entry sequence can be optimised according to the characteristics of the + current function (e.g. no stack use, leaf function etc.). */ + void output_func_prologue (f, frame_size) FILE *f; int frame_size; { - int reg, live_regs_mask = 0; + int reg, live_regs_mask = 0, live_regs = 0, live_float_regs = 0; int volatile_func = (optimize > 0 && TREE_THIS_VOLATILE (current_function_decl)); - + int frame_needed; /* Nonzero if we must stuff some register arguments onto the stack as if they were passed there. */ int store_arg_regs = 0; @@ -5484,13 +5584,22 @@ return_used_this_function = 0; lr_save_eliminated = 0; - - fprintf (f, "\t%s args = %d, pretend = %d, frame = %d\n", + frame_size += current_function_outgoing_args_size; + + frame_needed = arm_apcs_frame_needed (); + + fprintf (f, "\t%s args = %d, pretend = %d, frame = %d, alloca = %d\n", ASM_COMMENT_START, current_function_args_size, - current_function_pretend_args_size, frame_size); - fprintf (f, "\t%s frame_needed = %d, current_function_anonymous_args = %d\n", - ASM_COMMENT_START, frame_pointer_needed, - current_function_anonymous_args); + current_function_pretend_args_size, frame_size, + current_function_calls_alloca); + fprintf (f, "\t%s frame_needed = %d, anonymous_args = %d, regs_live[14] = %d\n", + ASM_COMMENT_START, frame_needed, + current_function_anonymous_args, + current_function_has_nonlocal_label, regs_ever_live[14]); + fprintf (f, "\t%s nonlocal_label = %d, nonlocal_goto = %d, clobbers lr = %d\n", + ASM_COMMENT_START, current_function_has_nonlocal_label, + current_function_has_nonlocal_goto, + function_really_clobbers_lr (get_insns ())); if (volatile_func) fprintf (f, "\t%s Volatile function.\n", ASM_COMMENT_START); @@ -5498,44 +5607,307 @@ if (current_function_anonymous_args && current_function_pretend_args_size) store_arg_regs = 1; - for (reg = 0; reg <= 10; reg++) - if (regs_ever_live[reg] && ! call_used_regs[reg]) - live_regs_mask |= (1 << reg); + lr_save_eliminated = 0; - if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM]) - live_regs_mask |= (1 << PIC_OFFSET_TABLE_REGNUM); + if (frame_needed) + { + /* For volatile functions, we do not need to save any call used + registers. */ + if (!volatile_func) + for (reg = 0; reg <= 10; reg++) + if (regs_ever_live[reg] && ! call_used_regs[reg]) + live_regs++, live_regs_mask |= (1 << reg); + + /* We can be sure that lr does not need to be saved if any of the + following conditions are satisfied: + a) not optimising + b) no registers to save + c) function does not have more than 4 arguments + d) function does not call alloca + e) function does not require any stack space + f) function does not clobber lr + g) function does not use a static chain + h) floating point registers don't need to be saved. */ + if (!(optimize == 0 + || live_regs_mask + || current_function_calls_alloca +#ifdef STATIC_CHAIN_INCOMING_REGNUM + || current_function_needs_context +#endif + || current_function_args_size + || frame_size != 0 + || function_really_clobbers_lr (get_insns ()))) + lr_save_eliminated = 1; - if (frame_pointer_needed) - live_regs_mask |= 0xD800; - else if (regs_ever_live[14]) + /* Check if any floating point registers need to be saved. */ + if (!volatile_func) + for (reg = 16; reg <= 23; reg++) + if (regs_ever_live[reg] && !call_used_regs[reg]) + { + lr_save_eliminated = 0; + break; + } + + if (!lr_save_eliminated) +#ifdef STATIC_CHAIN_INCOMING_REGNUM + if (current_function_needs_context) + { + if (current_function_pretend_args_size) + { + /* Saving registers r0-r3 and having a static chain means + that we have to fixup the saved sp in the stack frame + later. Set the live register mask to save fp, sp, lr + and pc. */ + live_regs_mask |= 0xe800; + } + else + { + /* Push registers sp, lr and pc onto the stack. */ + print_multi_reg (f, "stmfd", STACK_POINTER_REGNUM, + 0xe000, FALSE, 1); + + /* Set the live register mask to save fp. */ + live_regs_mask |= 0x0800; + } + } + else +#endif + { + live_regs_mask |= 0xd800; +#ifdef AOF_ASSEMBLER + if (flag_pic) + fprintf (f, "\tmov\t%s%s, %s%s\n", + REGISTER_PREFIX, reg_names[12] /* ip */, + REGISTER_PREFIX, + reg_names[PIC_OFFSET_TABLE_REGNUM]); + else +#endif + fprintf (f, "\tmov\t%s%s, %s%s\n", + REGISTER_PREFIX, reg_names[12] /* ip */, + REGISTER_PREFIX, + reg_names[STACK_POINTER_REGNUM]); + } + } + else { - if (! current_function_args_size - && ! function_really_clobbers_lr (get_insns ())) + /* We're not setting up an APCS stack frame. */ + if (!volatile_func) + for (reg = 0; reg <= 12; reg++) + if (regs_ever_live[reg] && ! call_used_regs[reg]) + live_regs++, live_regs_mask |= 1 << reg; + + /* We can be sure that lr does not need to be saved if any of the + following conditions are satisfied: + a) no registers to save + b) function does not use a static chain. */ + + if (live_regs_mask +#ifdef STATIC_CHAIN_INCOMING_REGNUM + || current_function_needs_context +#endif + || function_really_clobbers_lr (get_insns ())) + live_regs_mask |= 1 << 14; + else lr_save_eliminated = 1; + } + + if (lr_save_eliminated && regs_ever_live[14]) + fprintf (f,"\t%s I don't think this function clobbers lr\n", + ASM_COMMENT_START); + + if (current_function_pretend_args_size) + { + if (store_arg_regs) + print_multi_reg (f, "stmfd", STACK_POINTER_REGNUM, + ((0xf0 >> (current_function_pretend_args_size / 4)) + & 0xf), FALSE, 1); else - live_regs_mask |= 0x4000; + fprintf (f, "\tsub\t%s%s, %s%s, #%d\n", + REGISTER_PREFIX, reg_names[STACK_POINTER_REGNUM], + REGISTER_PREFIX, reg_names[STACK_POINTER_REGNUM], + current_function_pretend_args_size); } + /* Save the stack frame. */ if (live_regs_mask) - { - /* if a di mode load/store multiple is used, and the base register - is r3, then r4 can become an ever live register without lr - doing so, in this case we need to push lr as well, or we - will fail to get a proper return. */ + print_multi_reg (f, "stmfd", STACK_POINTER_REGNUM, + live_regs_mask, FALSE, 1); - live_regs_mask |= 0x4000; - lr_save_eliminated = 0; + /* Store any call-used floating point registers. */ + if (! volatile_func) + { + if (arm_fpu_arch == FP_SOFT2) + { + for (reg = 23; reg > 15; reg--) + if (regs_ever_live[reg] && !call_used_regs[reg]) + { + fprintf (f, "\tstfe\t%s%s, [%s%s, #-12]!\n", + REGISTER_PREFIX, reg_names[reg], + REGISTER_PREFIX, reg_names[STACK_POINTER_REGNUM]); + live_float_regs++; + } + } + else + { + int start_reg = 23; + for (reg = 23; reg > 15; reg--) + { + if (regs_ever_live[reg] && !call_used_regs[reg]) + { + if (start_reg - reg == 3) + { + fprintf (f, "\tsfmfd\t%s%s, 4, [%s%s]!\n", + REGISTER_PREFIX, reg_names[reg], + REGISTER_PREFIX, reg_names[STACK_POINTER_REGNUM]); + start_reg = reg - 1; + live_float_regs += 4; + } + } + else + { + if (start_reg != reg) + { + fprintf (f, "\tsfmfd\t%s%s, %d, [%s%s]!\n", + REGISTER_PREFIX, reg_names[reg + 1], + start_reg - reg, REGISTER_PREFIX, + reg_names[STACK_POINTER_REGNUM]); + live_float_regs += start_reg - reg; + } + start_reg = reg - 1; + } + } + if (start_reg != reg) + { + fprintf (f, "\tsfmfd\t%s%s, %d, [%s%s]!\n", + REGISTER_PREFIX, reg_names[reg + 1], + start_reg - reg, REGISTER_PREFIX, + reg_names[STACK_POINTER_REGNUM]); + live_float_regs += start_reg - reg; + } + } } - if (lr_save_eliminated) - fprintf (f,"\t%s I don't think this function clobbers lr\n", - ASM_COMMENT_START); + /* This is setup for returning when we have altered sp. */ + if (live_regs_mask && frame_needed) +#ifdef STATIC_CHAIN_INCOMING_REGNUM + if (current_function_needs_context) + { + /* add fp, sp, #. */ + output_add_imm (11 /* fp */, STACK_POINTER_REGNUM, + 12 + 4 * live_regs + 12 * live_float_regs); + fprintf (f, "\tmov\t%s%s, %s%s\n", + REGISTER_PREFIX, reg_names[STATIC_CHAIN_INCOMING_REGNUM], + REGISTER_PREFIX, reg_names[STATIC_CHAIN_REGNUM]); + } + else +#endif + { + /* sub fp, ip, #4 + (4 * stacked args). */ + output_add_imm (11 /* fp */, 12 /* ip */, + -4 - current_function_pretend_args_size); + } +#ifdef STATIC_CHAIN_INCOMING_REGNUM + else + if (current_function_needs_context) + fprintf (f, "\tmov\t%s%s, %s%s\n", + REGISTER_PREFIX, reg_names[STATIC_CHAIN_INCOMING_REGNUM], + REGISTER_PREFIX, reg_names[STATIC_CHAIN_REGNUM]); +#endif +#ifdef STATIC_CHAIN_INCOMING_REGNUM + /* Fixup the value of sp saved in the stack earlier which was wrong, + when we need to save some of a1-a4 and we have a static chain. */ + /* XXX No guarantees for support_apcs_float. */ + if (frame_needed && current_function_needs_context + && current_function_pretend_args_size) + { + /* add ip, fp, #. */ + output_add_imm (12 /* ip */, 11 /* fp */, + 4 + current_function_pretend_args_size); #ifdef AOF_ASSEMBLER if (flag_pic) - fprintf (f, "\tmov\t%sip, %s%s\n", REGISTER_PREFIX, REGISTER_PREFIX, - reg_names[PIC_OFFSET_TABLE_REGNUM]); + fprintf (f, "\tstr\t%s%s, [%s%s, #-8]\n", + REGISTER_PREFIX, reg_names[PIC_OFFSET_TABLE_REGNUM], + REGISTER_PREFIX, reg_names[ARG_POINTER_REGNUM]); + else +#endif + fprintf (f, "\tstr\t%s%s, [%s%s, #-8]\n", + REGISTER_PREFIX, reg_names[12] /* ip */, + REGISTER_PREFIX, reg_names[ARG_POINTER_REGNUM]); + } +#endif + + /* Output the stack checking code if needed. */ + if (arm_stack_check_needed () && !lr_save_eliminated) + { + rtx op; + int regno = STACK_POINTER_REGNUM; + + if (frame_size > 256) + { + /* Align stack check size so we can perform the subtraction + in just one instruction. */ + int align, stack_check_size; + + /* Use ip as a scratch register for the stack limit checks. */ + regno = 12; /* ip */ + + /* Align size is a power of 8 less than the highest power + in that particular range. */ + + align = last_bit_set (frame_size); + if (frame_size > (1 << align)) + align ++; + align = (align + 1) & ~1; + align = 1 << (align - 8); + stack_check_size = (frame_size + 1) & ~(align - 1); + output_add_imm (regno, STACK_POINTER_REGNUM, -stack_check_size); + } + + /* Different run-time environments may define their own stack + check support function names by re-defining ARM_STKOVF_SPLIT_BIG + and ARM_STKOVF_SPLIT_SMALL. */ + fprintf (f, "\tcmp\t%s%s, %s%s\n", + REGISTER_PREFIX, reg_names[regno], + REGISTER_PREFIX, reg_names[10] /* sl */); + op = gen_rtx (SYMBOL_REF, Pmode, + (frame_size > 256) ? ARM_STKOVF_SPLIT_BIG + : ARM_STKOVF_SPLIT_SMALL); + assemble_external_libcall (op); + output_asm_insn ("bllt\t%a0", &op); + } + if (frame_size) + { + /* Create the space needed for the data to be stored on the + stack. */ + output_add_imm (STACK_POINTER_REGNUM, + STACK_POINTER_REGNUM, -frame_size); + } + +#if HARD_FRAME_POINTER_REGNUM == FRAME_POINTER_REGNUM + /* If we are not optimising the function, or we are calling + builtin_alloca, then make v6/r9 point to the bottom of the stack. */ +#ifdef PREVENT_FP_CLOBBER + /* If we have defined PREVENT_FP_CLOBBER to prevent the assumed + clobbering of the stack pointer when builtin_alloca is called, + we do not need to make v6/r9 point to the stack. If we are going + to receive non-local gotos then we need to set v6 up. */ + if (! optimize + || (! PREVENT_FP_CLOBBER && current_function_calls_alloca) + || current_function_has_nonlocal_label + || current_function_has_nonlocal_goto) + fprintf (f, "\tmov\t%s%s, %s%s\n", + REGISTER_PREFIX, reg_names[FRAME_POINTER_REGNUM], + REGISTER_PREFIX, reg_names[STACK_POINTER_REGNUM]); +#else + if (! optimize || current_function_calls_alloca + || current_function_has_nonlocal_label + || current_function_has_nonlocal_goto) + fprintf (f, "\tmov\t%R%s, %s%s\n", + REGISTER_PREFIX, reg_names[FRAME_POINTER_REGNUM], + REGISTER_PREFIX, reg_names[STACK_POINTER_REGNUM]); +#endif #endif } @@ -5552,11 +5924,13 @@ int volatile_func = (optimize > 0 && TREE_THIS_VOLATILE (current_function_decl)); + frame_size += current_function_outgoing_args_size; /* NAB */ + if (use_return_insn (FALSE) && return_used_this_function) { - if ((frame_size + current_function_outgoing_args_size) != 0 - && !(frame_pointer_needed && TARGET_APCS)) + if (frame_size && ! TARGET_APCS) abort (); + goto epilogue_done; } @@ -5574,21 +5948,21 @@ goto epilogue_done; } - for (reg = 0; reg <= 10; reg++) - if (regs_ever_live[reg] && ! call_used_regs[reg]) - { - live_regs_mask |= (1 << reg); - floats_offset += 4; - } - if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM]) { live_regs_mask |= (1 << PIC_OFFSET_TABLE_REGNUM); floats_offset += 4; } - if (frame_pointer_needed) + if (arm_apcs_frame_needed ()) { + for (reg = 0; reg <= 10; reg++) + if (regs_ever_live[reg] && ! call_used_regs[reg]) + { + live_regs_mask |= (1 << reg); + floats_offset += 4; + } + if (arm_fpu_arch == FP_SOFT2) { for (reg = 23; reg > 15; reg--) @@ -5634,28 +6008,38 @@ REGISTER_PREFIX, reg_names[reg + 1], start_reg - reg, REGISTER_PREFIX, floats_offset); } - + if (TARGET_THUMB_INTERWORK) { live_regs_mask |= 0x6800; - print_multi_reg (f, "ldmea\t%sfp", live_regs_mask, FALSE); + print_multi_reg (f, "ldmea", 11, live_regs_mask, FALSE, 0); fprintf (f, "\tbx\t%slr\n", REGISTER_PREFIX); } else { live_regs_mask |= 0xA800; - print_multi_reg (f, "ldmea\t%sfp", live_regs_mask, - TARGET_APCS_32 ? FALSE : TRUE); + print_multi_reg (f, "ldmea", 11, live_regs_mask, + TARGET_APCS_32 ? FALSE : TRUE, 0); } } else { + for (reg = 0; reg <= 12; reg++) + if (regs_ever_live[reg] && ! call_used_regs[reg]) + { + live_regs_mask |= (1 << reg); + floats_offset += 4; + } + /* Restore stack pointer if necessary. */ - if (frame_size + current_function_outgoing_args_size != 0) + if (current_function_calls_alloca || frame_size) { - operands[0] = operands[1] = stack_pointer_rtx; - operands[2] = GEN_INT (frame_size - + current_function_outgoing_args_size); + operands[0] = stack_pointer_rtx; + if (current_function_calls_alloca) + operands[1] = gen_rtx_REG (SImode, FRAME_POINTER_REGNUM); + else + operands[1] = stack_pointer_rtx; + operands[2] = GEN_INT (frame_size); output_add_immediate (operands); } @@ -5708,7 +6092,8 @@ live_regs_mask |= 0x4000; if (live_regs_mask != 0) - print_multi_reg (f, "ldmfd\t%ssp!", live_regs_mask, FALSE); + print_multi_reg (f, "ldmfd", STACK_POINTER_REGNUM, + live_regs_mask | 0x4000, FALSE, 1); fprintf (f, "\tbx\t%slr\n", REGISTER_PREFIX); } @@ -5717,8 +6102,9 @@ : "\tmovs\t%spc, %slr\n"), REGISTER_PREFIX, REGISTER_PREFIX, f); else - print_multi_reg (f, "ldmfd\t%ssp!", live_regs_mask | 0x8000, - TARGET_APCS_32 ? FALSE : TRUE); + print_multi_reg (f, "ldmfd", STACK_POINTER_REGNUM, + live_regs_mask | 0x8000, + TARGET_APCS_32 ? FALSE : TRUE, 1); } else { @@ -5729,7 +6115,8 @@ live_regs_mask |= 0x4000; if (live_regs_mask != 0) - print_multi_reg (f, "ldmfd\t%ssp!", live_regs_mask, FALSE); + print_multi_reg (f, "ldmfd", STACK_POINTER_REGNUM, + live_regs_mask, FALSE, 1); } if (current_function_pretend_args_size) @@ -5754,6 +6141,7 @@ /* Reset the ARM-specific per-function variables. */ current_function_anonymous_args = 0; after_arm_reorg = 0; + arm_leaf_function = -1; } static void @@ -5831,113 +6219,6 @@ void arm_expand_prologue () { - int reg; - rtx amount = GEN_INT (-(get_frame_size () - + current_function_outgoing_args_size)); - int live_regs_mask = 0; - int store_arg_regs = 0; - int volatile_func = (optimize > 0 - && TREE_THIS_VOLATILE (current_function_decl)); - - /* Naked functions don't have prologues. */ - if (arm_naked_function_p (current_function_decl)) - return; - - if (current_function_anonymous_args && current_function_pretend_args_size) - store_arg_regs = 1; - - if (! volatile_func) - { - for (reg = 0; reg <= 10; reg++) - if (regs_ever_live[reg] && ! call_used_regs[reg]) - live_regs_mask |= 1 << reg; - - if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM]) - live_regs_mask |= 1 << PIC_OFFSET_TABLE_REGNUM; - - if (regs_ever_live[14]) - live_regs_mask |= 0x4000; - } - - if (frame_pointer_needed) - { - live_regs_mask |= 0xD800; - emit_insn (gen_movsi (gen_rtx_REG (SImode, 12), - stack_pointer_rtx)); - } - - if (current_function_pretend_args_size) - { - if (store_arg_regs) - emit_multi_reg_push ((0xf0 >> (current_function_pretend_args_size / 4)) - & 0xf); - else - emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, - GEN_INT (-current_function_pretend_args_size))); - } - - if (live_regs_mask) - { - /* If we have to push any regs, then we must push lr as well, or - we won't get a proper return. */ - live_regs_mask |= 0x4000; - emit_multi_reg_push (live_regs_mask); - } - - /* For now the integer regs are still pushed in output_func_epilogue (). */ - - if (! volatile_func) - { - if (arm_fpu_arch == FP_SOFT2) - { - for (reg = 23; reg > 15; reg--) - if (regs_ever_live[reg] && ! call_used_regs[reg]) - emit_insn (gen_rtx_SET - (VOIDmode, - gen_rtx_MEM (XFmode, - gen_rtx_PRE_DEC (XFmode, - stack_pointer_rtx)), - gen_rtx_REG (XFmode, reg))); - } - else - { - int start_reg = 23; - - for (reg = 23; reg > 15; reg--) - { - if (regs_ever_live[reg] && ! call_used_regs[reg]) - { - if (start_reg - reg == 3) - { - emit_sfm (reg, 4); - start_reg = reg - 1; - } - } - else - { - if (start_reg != reg) - emit_sfm (reg + 1, start_reg - reg); - start_reg = reg - 1; - } - } - - if (start_reg != reg) - emit_sfm (reg + 1, start_reg - reg); - } - } - - if (frame_pointer_needed) - emit_insn (gen_addsi3 (hard_frame_pointer_rtx, gen_rtx_REG (SImode, 12), - (GEN_INT - (-(4 + current_function_pretend_args_size))))); - - if (amount != const0_rtx) - { - emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, amount)); - emit_insn (gen_rtx_CLOBBER (VOIDmode, - gen_rtx_MEM (BLKmode, stack_pointer_rtx))); - } - /* If we are profiling, make sure no instructions are scheduled before the call to mcount. Similarly if the user has requested no scheduling in the prolog. */ @@ -6579,6 +6860,77 @@ } } +/* Given FROM and TO register numbers, say whether this elimination + is allowed. */ + +int +arm_can_eliminate (from, to) + int from, to; +{ + /* This should never happen but it does. */ + if (! optimize) + return 0; + + /* We can eliminate ARGP to STACKP if no alloca, no stack checks needed + and frame not needed. */ + if (from == ARG_POINTER_REGNUM + && to == STACK_POINTER_REGNUM + && ! arm_apcs_frame_needed ()) + return 1; + + /* FRAMEP can be eliminated to STACKP. */ + if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM) + return 1; + + /* Can't do any other eliminations. */ + return 0; +} + +/* Return 1 if the function prologue really needs to setup an APCS + frame. */ +int +arm_apcs_frame_needed () +{ + /* If we are not targeting the APCS, we will not use a stack frame. */ + if (! TARGET_APCS) + return 0; + + /* If we are not optimising, or we call alloca, we will always + setup a frame. */ + if (current_function_calls_alloca || ! optimize) + return 1; + + /* A frame will need to be setup for the cases where there are external + function calls within the current function or there is a need + for definite stack checking. */ + if (! arm_leaf_function_p () || arm_stack_check_needed ()) + return 1; + + return 0; +} + +/* Return 1 if the function prologue should contain an explicit + stack check. */ +static int +arm_stack_check_needed () +{ + /* Don't do any stack checking if it was not asked for. */ + if (! TARGET_APCS_STACK) + return 0; + + /* We will always use stack checking for non-optimising + circumstances. */ + if (! optimize) + return 1; + + /* Don't do any stack checking if the function is a leaf function + and the amount of stack actually needed <= 256 bytes. */ + if (arm_leaf_function_p () && abs (get_frame_size ()) <= 256) + return 0; + + return 1; +} + #ifdef AOF_ASSEMBLER /* Special functions only needed when producing AOF syntax assembler. */ @@ -6609,12 +6961,15 @@ for (offset = 0, chainp = &aof_pic_chain; *chainp; offset += 4, chainp = &(*chainp)->next) if ((*chainp)->symname == XSTR (x, 0)) - return plus_constant (aof_pic_label, offset); + { + /* AOF assembler that doesn't support BASED areas properly. */ + return GEN_INT (offset); + } *chainp = (struct pic_chain *) xmalloc (sizeof (struct pic_chain)); (*chainp)->next = NULL; (*chainp)->symname = XSTR (x, 0); - return plus_constant (aof_pic_label, offset); + return GEN_INT (offset); } void @@ -6721,12 +7076,19 @@ /* The AOF assembler needs this to cause the startup code to be extracted from the library. Brining in __main causes the whole thing to work automagically. */ +#if 0 if (arm_main_function) { text_section (); - fputs ("\tIMPORT __main\n", f); - fputs ("\tDCD __main\n", f); + + fputs ("\tIMPORT\t", f); + assemble_name (f, "__main"); + + fputs ("\n\tDCD\t", f); + assemble_name (f, "__main"); + fputc ('\n', f); } +#endif /* Now dump the remaining imports. */ while (imports_list) Index: gcc/config/arm/arm.h =================================================================== RCS file: /var/cvs/GCC-2.95/gcc/config/arm/arm.h,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- gcc/config/arm/arm.h 7 Feb 2005 22:50:23 -0000 1.1.1.1 +++ gcc/config/arm/arm.h 8 Feb 2005 01:20:34 -0000 1.2 @@ -72,6 +72,7 @@ /* This is needed by the tail-calling peepholes */ extern int frame_pointer_needed; +extern int lr_save_eliminated; /* Just in case configure has failed to define anything. */ @@ -188,7 +189,7 @@ " #ifndef CPP_APCS_PC_DEFAULT_SPEC -#define CPP_APCS_PC_DEFAULT_SPEC "-D__APCS_26__" +#define CPP_APCS_PC_DEFAULT_SPEC "-D__APCS_32__" #endif #define CPP_FLOAT_SPEC "\ @@ -471,8 +472,7 @@ /* The frame pointer register used in gcc has nothing to do with debugging; that is controlled by the APCS-FRAME option. */ -/* Not fully implemented yet */ -/* #define CAN_DEBUG_WITHOUT_FP 1 */ +#define CAN_DEBUG_WITHOUT_FP 1 #define TARGET_MEM_FUNCTIONS 1 @@ -685,7 +685,7 @@ #define FIXED_REGISTERS \ { \ 0,0,0,0,0,0,0,0, \ - 0,0,0,1,0,1,0,1, \ + 0,0,1,1,0,1,0,1, \ 0,0,0,0,0,0,0,0, \ 1,1,1 \ } @@ -701,7 +701,7 @@ #define CALL_USED_REGISTERS \ { \ 1,1,1,1,0,0,0,0, \ - 0,0,0,1,1,1,1,1, \ + 0,0,1,1,1,1,1,1, \ 1,1,1,1,0,0,0,0, \ 1,1,1 \ } @@ -775,13 +775,19 @@ #define STACK_POINTER_REGNUM 13 /* Base register for access to local variables of the function. */ +#ifdef TARGET_RISCOSAOF +#define FRAME_POINTER_REGNUM 9 +#else #define FRAME_POINTER_REGNUM 25 +#endif /* Define this to be where the real frame pointer is if it is not possible to work out the offset between the frame pointer and the automatic variables until after register allocation has taken place. FRAME_POINTER_REGNUM should point to a special register that we will make sure is eliminated. */ +#ifndef TARGET_RISCOSAOF #define HARD_FRAME_POINTER_REGNUM 11 +#endif /* Value should be nonzero if functions must have frame pointers. Zero means the frame pointer need not be set up (and parms may be accessed @@ -789,16 +795,32 @@ If we have to have a frame pointer we might as well make use of it. APCS says that the frame pointer does not need to be pushed in leaf functions, or simple tail call functions. */ +#ifdef TARGET_RISCOSAOF +#undef FRAME_POINTER_REQUIRED +#define FRAME_POINTER_REQUIRED 0 +#else #define FRAME_POINTER_REQUIRED \ (current_function_has_nonlocal_label || (TARGET_APCS && !leaf_function_p ())) +#endif /* Base register for access to arguments of the function. */ +#ifdef TARGET_RISCOSAOF +#define ARG_POINTER_REGNUM 11 +#else #define ARG_POINTER_REGNUM 26 +#endif /* The native (Norcroft) Pascal compiler for the ARM passes the static chain as an invisible last argument (possible since varargs don't exist in Pascal), so the following is not true. */ +#ifdef TARGET_RISCOSAOF +/* The register number as seen by the called function is r12/ip. */ +#define STATIC_CHAIN_REGNUM 12 +/* The register number as seen by the calling function is r8/v5. */ +#define STATIC_CHAIN_INCOMING_REGNUM 8 +#else #define STATIC_CHAIN_REGNUM 8 +#endif /* Register in which address to store a structure value is passed to a function. */ @@ -1011,13 +1033,21 @@ is at the high-address end of the local variables; that is, each additional local variable allocated goes at a more negative offset in the frame. */ +#ifdef TARGET_RISCOSAOF +#undef FRAME_GROWS_DOWNWARD +#else #define FRAME_GROWS_DOWNWARD 1 +#endif /* Offset within stack frame to start allocating local variables at. If FRAME_GROWS_DOWNWARD, this is the offset to the END of the first local allocated. Otherwise, it is the offset to the BEGINNING of the first local allocated. */ +#ifdef TARGET_RISCOSAOF +#define STARTING_FRAME_OFFSET (current_function_outgoing_args_size) +#else #define STARTING_FRAME_OFFSET 0 +#endif /* If we generate an insn to push BYTES bytes, this says how many the stack pointer really advances by. */ @@ -1226,63 +1256,70 @@ be eliminated; it is replaced with either the stack or the real frame pointer. */ +#ifdef TARGET_RISCOSAOF +#define ELIMINABLE_REGS \ +{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM },\ + { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM }} +#else #define ELIMINABLE_REGS \ {{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ {ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \ {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ {FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}} +#endif /* Given FROM and TO register numbers, say whether this elimination is allowed. - Frame pointer elimination is automatically handled. - - All eliminations are permissible. Note that ARG_POINTER_REGNUM and - HARD_FRAME_POINTER_REGNUM are in fact the same thing. If we need a frame - pointer, we must eliminate FRAME_POINTER_REGNUM into - HARD_FRAME_POINTER_REGNUM and not into STACK_POINTER_REGNUM. */ -#define CAN_ELIMINATE(FROM, TO) \ - (((TO) == STACK_POINTER_REGNUM && frame_pointer_needed) ? 0 : 1) + Frame pointer elimination is automatically handled. */ +#define CAN_ELIMINATE(FROM, TO) arm_can_eliminate ((FROM), (TO)) /* Define the offset between two registers, one to be eliminated, and the other its replacement, at the start of a routine. */ #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ { \ int volatile_func = arm_volatile_func (); \ - if ((FROM) == ARG_POINTER_REGNUM && (TO) == HARD_FRAME_POINTER_REGNUM)\ - (OFFSET) = 0; \ - else if ((FROM) == FRAME_POINTER_REGNUM \ - && (TO) == STACK_POINTER_REGNUM) \ - (OFFSET) = (current_function_outgoing_args_size \ - + ((get_frame_size () + 3) & ~3)); \ - else \ + /* The default. */ \ + (OFFSET) = 0; \ + if ((FROM) == ARG_POINTER_REGNUM || (TO) == ARG_POINTER_REGNUM) \ { \ int regno; \ - int offset = 12; \ + int offset = abs (get_frame_size ()) \ + + current_function_outgoing_args_size; \ int saved_hard_reg = 0; \ \ + /* Registers don't need to be saved in volatile functions. */ \ if (! volatile_func) \ { \ for (regno = 0; regno <= 10; regno++) \ if (regs_ever_live[regno] && ! call_used_regs[regno]) \ saved_hard_reg = 1, offset += 4; \ - /* PIC register is a fixed reg, so call_used_regs set. */ \ - if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM]) \ - saved_hard_reg = 1, offset += 4; \ for (regno = 16; regno <=23; regno++) \ if (regs_ever_live[regno] && ! call_used_regs[regno]) \ offset += 12; \ } \ - if ((FROM) == FRAME_POINTER_REGNUM) \ - (OFFSET) = -offset; \ + if (arm_apcs_frame_needed ()) \ + { \ + /* Take into account fp, ip, lr and pc. */ \ + offset += 16; \ + } \ else \ { \ - if (! frame_pointer_needed) \ - offset -= 16; \ - if (! volatile_func \ - && (regs_ever_live[14] || saved_hard_reg)) \ + /* Not targetting the APCS, only need to check r11, r12 */ \ + /* and lr. */ \ + if (! volatile_func) \ + { \ + for (regno = 11; regno <= 12; regno++) \ + if (regs_ever_live[regno] && !call_used_regs[regno]) \ + saved_hard_reg = 1, offset += 4; \ + if (regs_ever_live[14] || saved_hard_reg) \ offset += 4; \ - offset += current_function_outgoing_args_size; \ - (OFFSET) = ((get_frame_size () + 3) & ~3) + offset; \ } \ + /* Frame is now 4 too large. */ \ + offset -= 4; \ + } \ + if ((FROM) == FRAME_POINTER_REGNUM) \ + (OFFSET) -= offset; \ + else \ + (OFFSET) += offset; \ } \ } @@ -1313,18 +1350,6 @@ /* Alignment required for a trampoline in units. */ #define TRAMPOLINE_ALIGN 4 - -/* Emit RTL insns to initialize the variable parts of a trampoline. - FNADDR is an RTX for the address of the function's pure code. - CXT is an RTX for the static chain value for the function. */ -#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ -{ \ - emit_move_insn (gen_rtx_MEM (SImode, plus_constant ((TRAMP), 8)), \ - (CXT)); \ - emit_move_insn (gen_rtx_MEM (SImode, plus_constant ((TRAMP), 12)), \ - (FNADDR)); \ -} - /* Addressing modes, and classification of registers for them. */ @@ -2043,6 +2068,17 @@ GET_CODE (X) == POST_DEC ? "-" : "", \ GET_MODE_SIZE (output_memory_reference_mode)); \ } \ + else if (GET_CODE (X) == SYMBOL_REF && TARGET_APCS_STACK) \ + { \ + /* Convert setjmp and longjmp to alternative names for extra \ + processing. */ \ + if (strcmp (XSTR (X, 0), "setjmp") == 0) \ + assemble_name (STREAM, "___arm_alloca_setjmp"); \ + else if (strcmp (XSTR (X, 0), "longjmp") == 0) \ + assemble_name (STREAM, "___arm_alloca_longjmp"); \ + else \ + assemble_name (STREAM, XSTR (X, 0)); \ + } \ else output_addr_const(STREAM, X); \ } @@ -2245,6 +2281,8 @@ int short_branch PROTO ((int, int)); void assemble_align PROTO((int)); /* Used in arm.md, but defined in output.c */ int multi_register_push PROTO ((Rtx, Mmode)); +void arm_poke_function_name STDIO_PROTO ((FILE *, char *)); +int arm_can_eliminate PROTO ((int, int)); #ifdef AOF_ASSEMBLER Rtx aof_pic_entry PROTO ((Rtx)); void aof_dump_pic_table STDIO_PROTO ((FILE *)); Index: gcc/config/arm/arm.md =================================================================== RCS file: /var/cvs/GCC-2.95/gcc/config/arm/arm.md,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- gcc/config/arm/arm.md 7 Feb 2005 22:50:23 -0000 1.1.1.1 +++ gcc/config/arm/arm.md 8 Feb 2005 01:20:34 -0000 1.2 @@ -5980,7 +5980,8 @@ (return)] "(GET_CODE (operands[0]) == SYMBOL_REF && USE_RETURN_INSN(FALSE) && !get_frame_size () && !current_function_calls_alloca - && !frame_pointer_needed && !current_function_args_size)" + && !current_function_outgoing_args_size && !current_function_args_size + && lr_save_eliminated)" "* { extern rtx arm_target_insn; @@ -6008,7 +6009,8 @@ (return)] "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN(FALSE) && !get_frame_size () && !current_function_calls_alloca - && !frame_pointer_needed && !current_function_args_size)" + && !current_function_outgoing_args_size && !current_function_args_size + && lr_save_eliminated)" "* { extern rtx arm_target_insn; @@ -6040,7 +6042,8 @@ (return)] "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN(FALSE) && !get_frame_size () && !current_function_calls_alloca - && !frame_pointer_needed && !current_function_args_size)" + && !current_function_outgoing_args_size && !current_function_args_size + && lr_save_eliminated)" "* { extern rtx arm_target_insn; @@ -6276,3 +6279,140 @@ assemble_align (32); return \"\"; ") + +;; Implementations for dyamic allocation off the stack. + +;; These patterns say how to perform an equivalent to dynamic allocation +;; off the stack. We use library routines to return malloced memory +;; then alter the frame pointer so that on function exit, all chunks +;; will be freed. This system also works for different blocks within a +;; function. + +;; We do not need to worry about the outermost block in a function since +;; function exit will tidy up all unalloced chunks. + +(define_expand "save_stack_function" + [(use (const_int 0))] + "TARGET_APCS_STACK" + "") + +(define_expand "restore_stack_function" + [(use (const_int 0))] + "TARGET_APCS_STACK" + "") + +;; On entrance to a block, with __builtin_alloca, create a unique key +;; suitable for the free code. + +(define_expand "save_stack_block" + [(match_operand:SI 0 "memory_operand" "") + (match_operand:SI 1 "s_register_operand" "")] + "TARGET_APCS_STACK" + " +{ +#if 1 + /* Inline version of __arm_alloca_block_init. */ + rtx scratch_reg = gen_reg_rtx (SImode); + rtx label = gen_rtx_SYMBOL_REF (Pmode, \"__arm_alloca_st\"); + + emit_move_insn (scratch_reg, gen_rtx_MEM (SImode, label)); + emit_insn (gen_addsi3 (scratch_reg, scratch_reg, const1_rtx)); + emit_move_insn (gen_rtx_MEM (SImode, label), scratch_reg); +#else + rtx r0_rtx = gen_rtx (REG, SImode, 0); + rtx funexp = gen_rtx (SYMBOL_REF, Pmode, \"___arm_alloca_block_init\"); + + emit_call_insn (gen_call_value (r0_rtx, + gen_rtx (MEM, FUNCTION_MODE, funexp), + const0_rtx)); + emit_move_insn (operands[0], r0_rtx); +#endif + DONE; +}") + +(define_expand "save_stack_nonlocal" + [(match_operand:SI 0 "memory_operand" "") + (match_operand:SI 1 "s_register_operand" "")] + "TARGET_APCS_STACK" + " +{ +#if 1 + /* Inline version of __arm_alloca_block_init. */ + rtx scratch_reg = gen_reg_rtx (SImode); + rtx label = gen_rtx_SYMBOL_REF (Pmode, \"__arm_alloca_st\"); + + emit_move_insn (scratch_reg, gen_rtx_MEM (SImode, label)); + emit_insn (gen_addsi3 (scratch_reg, scratch_reg, const1_rtx)); + emit_move_insn (gen_rtx_MEM (SImode, label), scratch_reg); +#else + rtx r0_rtx = gen_rtx (REG, SImode, 0); + rtx funexp = gen_rtx (SYMBOL_REF, Pmode, \"___arm_alloca_block_init\"); + + emit_call_insn (gen_call_value (r0_rtx, + gen_rtx (MEM, FUNCTION_MODE, funexp), + const0_rtx)); + emit_move_insn (operands[0], r0_rtx); +#endif + DONE; +}") + + +;; Use the unique key produced earlier to free chunks created under +;; this key. + +(define_expand "restore_stack_block" + [(set (match_dup 2) (mem:SI (match_operand:SI 0 "s_register_operand" ""))) + (set (match_dup 0) (match_operand:SI 1 "s_register_operand" "")) + (set (mem:SI (match_dup 0)) (match_dup 2))] + "TARGET_APCS_STACK" + " +{ + rtx r0_rtx = gen_rtx (REG, SImode, 0); + rtx funexp = gen_rtx (SYMBOL_REF, Pmode, \"___arm_alloca_block_free\"); + + emit_move_insn (r0_rtx, operands[1]); + emit_insn (gen_rtx (USE, VOIDmode, r0_rtx)); + emit_call_insn (gen_call (gen_rtx (MEM, FUNCTION_MODE, funexp), GEN_INT (4))); + DONE; +}") + +(define_expand "restore_stack_nonlocal" + [(match_operand:SI 0 "s_register_operand" "") + (match_operand:SI 1 "memory_operand" "")] + "TARGET_APCS_STACK" + " +{ + rtx r0_rtx = gen_rtx (REG, SImode, 0); + rtx funexp = gen_rtx (SYMBOL_REF, Pmode, \"___arm_alloca_block_free\"); + + emit_move_insn (r0_rtx, operands[1]); + emit_insn (gen_rtx (USE, VOIDmode, r0_rtx)); + emit_call_insn (gen_call (gen_rtx (MEM, FUNCTION_MODE, funexp), GEN_INT (4))); + DONE; +}") + + +;; Call the function that will reserve the necessary amount of memory + +(define_expand "allocate_stack" + [(set (match_operand:SI 0 "s_register_operand" "=r") + (minus:SI (reg:SI 13) (match_operand:SI 1 "reg_or_int_operand" ""))) + (set (reg:SI 13) + (minus:SI (reg:SI 13) (match_dup 1))) + (clobber (reg:SI 0)) + (clobber (reg:SI 14))] + "TARGET_APCS_STACK" + " +{ + rtx r0_rtx = gen_rtx (REG, SImode, 0); + rtx funexp = gen_rtx (SYMBOL_REF, Pmode, \"___arm_alloca_alloc\"); + + emit_move_insn (r0_rtx, operands[1]); + emit_insn (gen_rtx (USE, VOIDmode, r0_rtx)); + emit_call_insn (gen_call_value (r0_rtx, + gen_rtx (MEM, FUNCTION_MODE, funexp), + GEN_INT (4))); + emit_move_insn (operands[0], r0_rtx); + + DONE; +}") Index: gcc/config/arm/lib1aof.s =================================================================== RCS file: gcc/config/arm/lib1aof.s diff -N gcc/config/arm/lib1aof.s --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ gcc/config/arm/lib1aof.s 8 Feb 2005 01:20:34 -0000 1.1 @@ -0,0 +1,1948 @@ +/* libgcc1 and libgcc2 routines for ARM cpu (AOF format) + Copyright (C) 1998, 2000 Free Software Foundation, Inc. + Contributed by Nick Burrett (nick.burrett@btinternet.com) + and Peter Burwood (pjb@arcangel.dircon.co.uk) + + 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 + the Free Software Foundation; either version 2, or (at your option) + any later version. + + In addition to the permissions in the GNU General Public License, the + Free Software Foundation gives you unlimited permission to link the + compiled version of this file with other programs, and to distribute + those programs without any restriction coming from the use of this + file. (The General Public License restrictions do apply in other + respects; for example, they cover modification of the file, and + distribution when not linked into another program.) + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + As a special exception, if you link this library with other files, + some of which are compiled with GCC, to produce an executable, + this library does not by itself cause the resulting executable + to be covered by the GNU General Public License. + This exception does not however invalidate any other reasons why + the executable file might be covered by the GNU General Public License. */ + +/* Run this through cpp */ + +a1 RN 0 +a2 RN 1 +a3 RN 2 +a4 RN 3 +v1 RN 4 +v2 RN 5 +v3 RN 6 +v4 RN 7 +v5 RN 8 +v6 RN 9 +sl RN 10 +fp RN 11 +ip RN 12 +sp RN 13 +lr RN 14 +pc RN 15 +f0 FN 0 +f1 FN 1 +f2 FN 2 +f3 FN 3 +f4 FN 4 +f5 FN 5 +f6 FN 6 +f7 FN 7 +r0 RN 0 +r1 RN 1 +r2 RN 2 +r3 RN 3 +r4 RN 4 +r12 RN 12 +r14 RN 14 + +#ifdef __APCS_26__ +#define RETURN(dst,src) movs dst, src +#define RETURNc(x,dst,src) mov##x##s dst, src +#define RETCOND ^ +#else +#define RETURN(dst,src) mov dst, src +#define RETURNc(x,dst,src) mov##x dst, src +#define RETCOND +#endif + +/* Keep these in sync with unixlib/asm_dec.s and features.h */ +__FEATURE_PTHREADS EQU 1 +__PTHREAD_ALLOCA_OFFSET EQU 8 + + AREA |C$$code|, CODE, READONLY + +#ifdef L_ashldi3 + EXPORT |__ashldi3| + +/* DItype __ashldi3 (DItype u, word_type b) + a1, a2 = u + a3 = b */ +|__ashldi3| + /* if shift = 0 then return */ + CMP a3, #0 + RETURNc(eq, pc, lr) + + /* if shift >= 32 then low word will be 0 */ + RSBS ip, a3, #32 /* bm = 32 - b */ + RSBLE ip, ip, #0 + MOVLE a2, a1, ASL ip /* high = low << -bm */ + MOVLE a1, #0 /* low = 0 */ + + MOVGT a2, a2, LSL a3 /* high = high << b */ + ORRGT a2, a2, a1, LSR ip /* high = high | low >> bm */ + MOVGT a1, a1, ASL a3 /* low = low << b */ + + RETURN(pc, lr) +#endif + +#ifdef L_ashrdi3 + EXPORT |__ashrdi3| +/* DItype __ashrdi3 (DItype u, word_type b) + a1, a2 = u + a3 = b */ +|__ashrdi3| + /* if shift = 0 then return */ + CMP a3, #0 + RETURNc(eq, pc, lr) + + /* if shift >= 32 then high word will be 1..1 or 0..0 */ + RSBS ip, a3, #32 /* bm = 32 - b */ + RSBLE ip, ip, #0 + MOVLE a1, a2, ASR ip /* low = high >> - bm */ + MOVLE a2, a2, ASR #31 /* high = high >> 31 */ + + MOVGT a1, a1, LSR a3 /* low = low >> b */ + ORRGT a1, a1, a2, ASL ip /* low = low | high << bm */ + MOVGT a2, a2, ASR a3 /* high = high >> b */ + + RETURN(pc, lr) +#endif + +#ifdef L_clear_icache + EXPORT |__clear_icache| + /* clear instruction cache + + On entry + R0 = low address of range (word aligned) + R1 = high address (word aligned, _inclusive_) */ + +X_Bit EQU &020000 +XOS_SynchroniseCodeAreas EQU &00006E + X_Bit + +|__clear_icache| + MOV a3, a2 + MOV a2, a1 + MOV a1, #1 + SWI XOS_SynchroniseCodeAreas + RETURN(pc, lr) +#endif + +#ifdef L_cmpdi2 + EXPORT |__cmpdi2| + /* compare two long long ints + enter with __cmpdi2 (DItype a, DItype b) + entry a1,a2 = u, a3,a4 = v + exit u > v = 2, u < v = 0, u = v = 1 */ +|__cmpdi2| + CMP a2, a4 + CMPEQ a1, a3 + MOVLT a1, #0 + MOVGT a1, #2 + MOVEQ a1, #1 + RETURN(pc, lr) +#endif + +#ifdef L_divdi3 + EXPORT |__divdi3| + IMPORT |__div0| + + /* (a1, a2) / (a3, a4) + result in v2 and v3 + remainder in v4 and ip */ +|__divdi3| + /* fast exits + check the numerator for zero */ + CMP a1, #0 /* low */ + CMPEQ a2, #0 /* high */ + RETURNc(eq, pc, lr) + /* test for a divide by zero */ + CMP a3, #0 /* low */ + CMPEQ a4, #0 /* high */ + BEQ |__div0| /* divide by zero. */ + /* No stack checking since we are a leaf function. + We don't need to store ip - procedure calling standard + lets it be corrupted. */ + STMFD sp!, {v2, v3, v4, v6, lr} + /* v6 = sign bit */ + ANDS v6, a4, #&80000000 + BPL |__divdi3.L00| + RSBS a3, a3, #0 /* low */ + RSC a4, a4, #0 /* high */ +|__divdi3.L00| + EORS v6, v6, a2, ASR#32 + BCC |__divdi3.L01| + RSBS a1, a1, #0 /* low */ + RSC a2, a2, #0 /* high */ +|__divdi3.L01| + /* initialise the quotient to zero */ + MOV v2, #0 /* low */ + MOV v3, #0 /* high */ + /* remainder = numerator */ + MOV v4, a1 /* low */ + MOV ip, a2 /* high */ + + /* lr is a count of the number of shifts needed */ + MOVS lr, #0 + /* shift the denominator left until the next doubling + generates a number larger than the numerator. + Count the number of shifts needed */ +|__divdi3.bit_count| + /* double the denominator, we've finished when the top bit + is set. */ + ADDS a3, a3, a3 /* low */ + ADCS a4, a4, a4 /* high */ + /* too big so we've finished */ + BCS |__divdi3.count_done| + CMP a4, ip /* high */ + CMPEQ a3, v4 /* low */ + /* if denominator is lower or the same as the numerator + signify an extra shift and carry on. */ + ADDLS lr, lr, #1 + BLS |__divdi3.bit_count| + + /* clear the carry flag */ + ADDS lr, lr, #0 + +|__divdi3.count_done| + /* we've overflowed. shift the denominator back down + to bring in the overflowed bit */ + MOVS a4, a4, RRX /* high */ + MOV a3, a3, RRX /* low */ + +|__divdi3.division| + /* numerator = remainder - denominator */ + SUBS a1, v4, a3 /* low */ + SBCS a2, ip, a4 /* high */ + /* if (remainder >= denominator) remainder = numerator */ + MOVCS v4, a1 /* low */ + MOVCS ip, a2 /* high */ + /* place next bit into the result */ + ADCS v2, v2, v2 /* low */ + ADC v3, v3, v3 /* high */ + /* shift the denominator right 1 bit */ + MOVS a4, a4, LSR #1 /* high */ + MOV a3, a3, RRX /* low */ + SUBS lr, lr, #1 + BGE |__divdi3.division| + /* result */ + MOVS v6, v6, LSL#2 + MOVCC a1, v2 + MOVCC a2, v3 + LDMCCFD sp!, {v2, v3, v4, v6, pc}RETCOND + RSBS a1, v2, #0 /* low */ + RSC a2, v3, #0 /* high */ + LDMFD sp!, {v2, v3, v4, v6, pc}RETCOND +#endif + +#ifdef L_divsi3 + EXPORT |__divsi3| + EXPORT |__divmodsi4| + IMPORT |__div0| + +|__divsi3| +|__divmodsi4| + MOVS a4, a2 + BEQ |__div0| /* divide by zero. */ + AND a3, a1, #&80000000 + EOR ip, a4, a1 + ORR a3, a3, ip, LSR #1 + RSBMI a4, a4, #0 + MOVS a2, a1 + RSBMI a2, a2, #0 + MOV ip, a4 + + CMP ip, a2, LSR #16 + MOVLS ip, ip, LSL #16 + CMP ip, a2, LSR #8 + MOVLS ip, ip, LSL #8 + CMP ip, a2, LSR #4 + MOVLS ip, ip, LSL #4 + CMP ip, a2, LSR #2 + MOVLS ip, ip, LSL #2 + CMP ip, a2, LSR #1 + MOVLS ip, ip, LSL #1 + + MOV a1, #0 +|__divsi3.divloop| + CMP a2, ip + SUBCS a2, a2, ip + ADC a1, a1, a1 + MOV ip, ip, LSR #1 + CMP ip, a4 + BCS |__divsi3.divloop| + TST a3, #&40000000 + RSBNE a1, a1, #0 + /* This line is for __divmodsi4 only */ + TST a3, #&80000000 + RSBNE a2, a2, #0 + RETURN(pc, lr) +#endif + +#ifdef L_ffs + EXPORT |ffs| + + /* return index to least significant 1-bit of a1 */ +|ffs| + /* input and output in a1, workspace a2 */ + TEQ a1, #0 /* test equality with 0 */ + SUBNE a2, a1, #1 /* subtract if not equal */ + EORNE a1, a1, a2 /* exclusive or if not equal */ + RSBNE a1, a1, a1, LSL #3 /* reverse subtract if not equal */ + RSBNE a1, a1, a1, LSL #8 + RSBNE a1, a1, a1, LSL #8 + RSBNE a1, a1, a1, LSL #8 + /* load register, if not equal, with byte */ + LDRNEB a1, [pc, a1, LSR #26] + RETURN(pc, lr) + +|ffs.table| + /* table must occur 8 bytes after LDRxxB instruction above */ + DCB 0,1,0,16,0,2,29,0,17,0,0,0,3,22,30,0 + DCB 0,0,20,18,11,0,13,0,0,4,0,7,0,23,31,0 + DCB 15,0,28,0,0,0,21,0,19,10,12,0,6,0,0,14 + DCB 27,0,0,9,0,5,0,26,0,8,25,0,24,0,32,0 + + EXPORT |__ffsdi2| +|__ffsdi2| + CMP a1, #0 /* if passed 0 */ + CMPEQ a2, #0 /* then exit */ + RETURNc(eq, pc, lr) + /* input and output in a1, workspace a2 */ + TEQ a1, #0 /* test equality with 0 */ + MOVEQ a1, a2 /* use the high word */ + MOVEQ a3, #32 /* need to add extra 32 bits */ + MOVNE a3, #0 /* use the low word */ + SUB a2, a1, #1 /* subtract if not equal */ + EOR a1, a1, a2 /* exclusive or if not equal */ + RSB a1, a1, a1, LSL #3 /* reverse subtract if not equal */ + RSB a1, a1, a1, LSL #8 + RSB a1, a1, a1, LSL #8 + RSB a1, a1, a1, LSL #8 + /* load register, if not equal, with byte */ + ADD a4, pc, #|ffs.table| - . - 8 + LDRB a1, [a4, a1, LSR #26] + ADD a1, a1, a3 + RETURN(pc, lr) +#endif + +#ifdef L_fixsfdi + EXPORT |__fixsfdi| + /* Convert single precision float to 64-bit int */ +|__fixsfdi| + cmp r0, #0 + moveq r1, #0 + RETURNc(eq, pc, lr) + + mov r2, r0, lsr #23 /* Extract the exponent */ + ands r2, r2, #&ff + bic r0, r0, r2, lsl #23 /* Clear exponent from mantissa */ + orrne r0, r0, #1<<23 /* add implicit bit */ + + tst r2, #1<<8 /* Is sign bit set */ + rsbne r0, r0, #0 /* yes; negate mantissa */ + + bic r2, r2, #1<<8 /* clear sign bit, leaving exponent */ + + subs r2, r2, #150 /* remove bias from exponent */ + movlt r0, r0, asr r2 + movlt r1, #0 + RETURNc(lt, pc, lr) + + rsb r2, r2, #0 + + /* perform 64-bit shift */ + rsbs ip, r2, #32 + rsble ip, ip, #0 /* shift >= 32 bits */ + movle r1, r0, asl ip + movle r0, #0 + movgt r1, r0, lsr ip + movgt r0, r0, asl r2 + RETURN(pc, lr) + + + /* number is represented as 1.mantissa x 2^exponent-127 */ + subs r2, r2, #127 /* remove bias from exponent */ + movmi r0, #0 /* if exponent negative then not representable */ + movmi r1, #0 + RETURNc(mi, pc, lr) /* as an integer */ + + /* the mantissa is 23 bits wide. assume we are representing the */ + /* number as mantissa x 2^23, then we may need to shift left */ + /* or right. */ + rsbs r2, r2, #23 + movpl r0, r0, asr r2 + movpl r1, #0 + RETURNc(pl, pc, lr) + + rsb r2, r2, #0 /* exponent was larger than 23 */ + + /* perform 64-bit shift */ + rsbs ip, r2, #32 + rsble ip, ip, #0 /* shift >= 32 bits */ + movle r1, r0, asl ip + movle r0, #0 + movgt r1, r0, lsr ip + movgt r0, r0, asl r2 + RETURN(pc, lr) +#endif + +#ifdef L_fixunssfdi + EXPORT |__fixunssfdi| + /* Convert single precision float to 64-bit int */ +|__fixunssfdi| + cmp r0, #0 + moveq r1, #0 + RETURNc(eq, pc, lr) + + mov r2, r0, lsr #23 /* Extract the exponent */ + bic r0, r0, r2, lsl #23 /* Clear exponent from mantissa */ + orr r0, r0, #1<<23 /* add implicit bit */ + bic r2, r2, #1<<8 /* clear sign bit, leaving exponent */ + + /* number is represented as 1.mantissa x 2^exponent-127 */ + subs r2, r2, #127 /* remove bias from exponent */ + movmi r0, #0 /* if exponent negative then not representable */ + movmi r1, #0 + RETURNc(mi, pc, lr) /* as an integer */ + + /* the mantissa is 23 bits wide. assume we are representing the */ + /* number as mantissa x 2^23, then we may need to shift left */ + /* or right. */ + rsbs r2, r2, #23 + movpl r0, r0, lsr r2 + movpl r1, #0 + RETURNc(pl, pc, lr) + + rsb r2, r2, #0 /* exponent was larger than 23 */ + + /* perform 64-bit shift */ + rsbs ip, r2, #32 + rsble ip, ip, #0 /* shift >= 32 bits */ + movle r1, r0, asl ip + movle r0, #0 + movgt r1, r0, lsr ip + movgt r0, r0, asl r2 + RETURN(pc, lr) +#endif + +#ifdef L_fixunsdfdi + EXPORT |__fixdfdi| + EXPORT |__fixunsdfdi| + +|__fixdfdi| + stmfd sp!, {r14} + mov r2, r0, lsr #31 + tst r2, #1 + bl |__fixunsdfdi| + ldmeqfd sp!, {pc}RETCOND + rsbs r0, r0, #0 + rsc r1, r1, #0 + ldmfd sp!, {pc}RETCOND + + /* Convert double precision float to 64-bit int */ +|__fixunsdfdi| + /* Check fast case, incoming integer == 0 */ + cmp r0, #0 + cmpeq r1, #0 + RETURNc(eq, pc, lr) + + /* r0 = first word */ + /* r1 = second word */ + + mov r3, r0, lsr #20 /* Extract the exponent */ + bic r2, r0, r3, lsl #20 /* clear exponent from fraction */ + orr r2, r2, #1<<20 /* add implicit bit */ + bic r12, r3, #1<<11 /* clear sign bit, leaving exponent */ + + /* number is represented as 1.mantissa x 2^exponent-1023 */ + sub r12, r12, #1024 /* remove bias from exponent */ + adds r12, r12, #1 + movmi r0, #0 /* if exponent negative then not representable */ + movmi r1, #0 /* as an integer */ + RETURNc(mi, pc, lr) + + /* at this point: r0 = exponent */ + /* r1 = second word (bottom 32-bits of fraction) */ + /* r2 = first word (top 20-bits of fraction) */ + + rsbs r12, r12, #52 + bmi fixunsdfdi_shl + + rsbs r3, r12, #32 /* r3 = 32 - shift */ + rsble r3, r3, #0 + movle r0, r2, lsr r3 /* low = high >> -bm */ + movle r1, #0 /* high = 0 */ + movgt r0, r1, lsr r12 /* low >>= exponent */ + orrgt r0, r0, r2, lsl r3 /* low |= high << r3 */ + movgt r1, r2, lsr r12 + RETURN(pc, lr) + +fixunsdfdi_shl + rsb r12, r12, #0 /* exponent was larger than 52 */ + + /* perform 64-bit shift */ + rsbs r3, r12, #32 + rsble r3, r3, #0 /* shift >= 32 bits */ + movle r1, r1, asl r3 + movle r0, #0 + movgt r2, r2, lsl r12 /* shift <= 31 bits */ + movgt r0, r1, asl r12 + orrgt r1, r2, r1, lsr r3 + RETURN(pc, lr) +#endif + +#ifdef L_fixunsxfdi + EXPORT |__fixxfdi| + EXPORT |__fixunsxfdi| + +|c..2| + DCD 0x4F000000 /* 2147483648.0 */ + +|__fixxfdi| + STMFD sp!, {a1, a2, a3} + LDFE f2, [sp], #12 + CMFE f2, #0.0 + BGE |__fixuns| + MOV a4, lr + MNFE f2, f2 + BL |__fixuns| + RSBS a1, a1, #0 + RSC a2, a2, #0 + RETURN(pc, a4) + + /* On entry: + sp = pointer to the floating point value + On exit: + r0 = lowest significant word of double integer + r1 = highest significant word of double integer */ +|__fixunsxfdi| + STMFD sp!, {a1, a2, a3} + LDFE f2, [sp], #12 + +|__fixuns| + CMFE f2, #0.0 + MOVLE a1, #0 + MOVLE a2, #0 + RETURNc(le, pc, lr) + LDFS f1, [pc, #|c..1| - . - 8] + FMLS f0, f1, #2.0 + DVFE f0, f2, f0 + CMFE f0, f1 + FIXLTZ a2, f0 + SUFGEE f0, f0, f1 + FIXGEZ a2, f0 + EORGE a2, a2, #&80000000 + MOV a1, #0 + CMP a2, #0 + RSBLT a3, a2, #0 + FLTLTE f0, a3 + MNFLTE f0, f0 + FLTGEE f0, a2 + MUFE f0, f0, f1 + MUFE f0, f0, #2.0 + SUFE f2, f2, f0 + CMFE f2, #0.0 + MNFLTE f2, f2 + MOVLT ip, #0 + MOVGE ip, #1 + CMFE f2, f1 + FIXLTZ a3, f2 + SUFGEE f2, f2, f1 + FIXGEZ a3, f2 + EORGE a3, a3, #&80000000 + CMP ip, #0 + BNE |do_add.2| + SUBS a1, a1, a3 + SBC a2, a2, #0 + RETURN(pc, lr) +|do_add.2| + ADDS a1, a1, a3 + ADC a2, a2, #0 + RETURN(pc, lr) +#endif + +#ifdef L_floatdidf + /* On entry: + r0 = lowest significant word of double integer + r1 = highest significant word of double integer + On exit: + f0 = A floating point representation of the integer */ + + /* Convert 64-bit integer to 96-bit float */ + EXPORT |__floatdixf| + /* Convert 64-bit integer to 64-bit float */ + EXPORT |__floatdidf| + /* Convert 64-bit integer to 32-bit float */ + EXPORT |__floatdisf| +|__floatdixf| +|__floatdidf| +|__floatdisf| + /* Check fast case, incoming integer == 0 */ + cmp r0, #0 + cmpeq r1, #0 + mvfeqd f0, #0.0 + RETURNc(eq, pc, lr) + + tst r1, #1<<31 + moveq r2, r0 /* bottom word */ + moveq r3, r1 /* top word */ + moveq r0, #0 /* first word of IEEE result */ + rsbne r2, r0, #0 /* negate fraction */ + rsbne r3, r1, #0 + movne r0, #1<<31 /* first word of IEEE result (with sign bit) */ + + cmp r3, #0 /* if top word if 0 then we'll use the bottom word */ + movne r12, #64 /* exponent */ + moveq r12, #32 + moveq r3, r2 + moveq r2, #0 + + /* Do a little loop unrolling */ + cmp r3, #1<<8 + movcc r3, r3, lsl #23 + orrcc r3, r3, r2, lsr #32-23 + movcc r2, r2, lsl #23 + subcc r12, r12, #23 + cmp r3, #1<<16 + movcc r3, r3, lsl #15 + orrcc r3, r3, r2, lsr #32-15 + movcc r2, r2, lsl #15 + subcc r12, r12, #15 + cmp r3, #1<<24 + movcc r3, r3, lsl #7 + orrcc r3, r3, r2, lsr #32-7 + movcc r2, r2, lsl #7 + subcc r12, r12, #7 +fltdidf_norm + tst r3, #1<<31 + bne fltdidf_norm_fin + mov r3, r3, lsl #1 + movs r2, r2, lsl #1 + orrcs r3, r3, #1 + sub r12, r12, #1 + b fltdidf_norm + +fltdidf_norm_fin + add r12, r12, #1020 /* add bias to exponent */ + add r12, r12, #2 + + /* pack into IEEE double precision format */ + orr r0, r0, r12, lsl #20 /* exponent */ + bic r3, r3, #1<<31 + orr r0, r0, r3, lsr #11 + mov r1, r2, lsr #11 + orr r1, r1, r3, lsl #21 + str r0, [sp, #-8] + str r1, [sp, #-4] + ldfd f0, [sp, #-8] + RETURN(pc, lr) +#endif + +#ifdef L_lshrdi3 + EXPORT |__lshrdi3| + + /* DItype __lshrdi3 (DItype u, word_type b) + a1, a2 = u + a3 = b */ +|__lshrdi3| + /* if shift = 0 then return */ + CMP a3, #0 + RETURNc(eq, pc, lr) + + /* if shift >= 32 then high word will be 0 */ + RSBS ip, a3, #32 /* bm = 32 - b */ + RSBLE ip, ip, #0 + MOVLE a1, a2, LSR ip /* low = high >> - bm */ + MOVLE a2, #0 /* high = 0 */ + + MOVGT a1, a1, LSR a3 /* low = low >> b */ + ORRGT a1, a1, a2, ASL ip /* low = low | high << bm */ + MOVGT a2, a2, LSR a3 /* high = high >> b */ + RETURN(pc, lr) +#endif + +#ifdef L_moddi3 + EXPORT |__moddi3| + IMPORT |__div0| + + /* (a1, a2) / (a3, a4) + result in v2 and v3 + remainder in v4 and ip */ +|__moddi3| + /* fast exits + check the numerator for zero */ + CMP a1, #0 /* low */ + CMPEQ a2, #0 /* high */ + RETURNc(eq, pc, lr) + /* test for a divide by zero */ + CMP a3, #0 /* low */ + CMPEQ a4, #0 /* high */ + BEQ |__div0| /* divide by zero. */ + /* No stack checking since we are a leaf function. + We don't need to store ip - procedure calling standard + lets it be corrupted. */ + STMFD sp!, {v2, v3, v4, v6, lr} + /* v6 = sign bit */ + ANDS v6, a4, #&80000000 + BPL |__moddi3.L00| + RSBS a3, a3, #0 /* low */ + RSC a4, a4, #0 /* high */ +|__moddi3.L00| + EORS v6, v6, a2, ASR#32 + BCC |__moddi3.L01| + RSBS a1, a1, #0 /* low */ + RSC a2, a2, #0 /* high */ +|__moddi3.L01| + /* initialise the quotient to zero */ + MOV v2, #0 /* low */ + MOV v3, #0 /* high */ + /* remainder = numerator */ + MOV v4, a1 /* low */ + MOV ip, a2 /* high */ + + /* lr is a count of the number of shifts needed */ + MOVS lr, #0 + /* shift the denominator left until the next doubling + generates a number larger than the numerator. + Count the number of shifts needed */ +|__moddi3.bit_count| + /* double the denominator, we've finished when the top bit + is set. */ + ADDS a3, a3, a3 /* low */ + ADCS a4, a4, a4 /* high */ + /* too big so we've finished */ + BCS |__moddi3.count_done| + CMP a4, ip /* high */ + CMPEQ a3, v4 /* low */ + /* if denominator is lower or the same as the numerator + signify an extra shift and carry on. */ + ADDLS lr, lr, #1 + BLS |__moddi3.bit_count| + + /* clear the carry flag */ + ADDS lr, lr, #0 + +|__moddi3.count_done| + /* we've overflowed. shift the denominator back down + to bring in the overflowed bit */ + MOVS a4, a4, RRX /* high */ + MOV a3, a3, RRX /* low */ + +|__moddi3.division| + /* numerator = remainder - denominator */ + SUBS a1, v4, a3 /* low */ + SBCS a2, ip, a4 /* high */ + /* if (remainder >= denominator) remainder = numerator */ + MOVCS v4, a1 /* low */ + MOVCS ip, a2 /* high */ + /* shift the denominator right 1 bit */ + MOVS a4, a4, LSR #1 /* high */ + MOV a3, a3, RRX /* low */ + SUBS lr, lr, #1 + BGE |__moddi3.division| + /* result */ + MOVS v6, v6, LSL#1 + MOVCC a1, v4 /* low */ + MOVCC a2, ip /* high */ + LDMCCFD sp!, {v2, v3, v4, v6, pc}RETCOND + RSBS a1, v4, #0 /* low */ + RSC a2, ip, #0 /* high */ + LDMFD sp!, {v2, v3, v4, v6, pc}RETCOND +#endif + +#ifdef L_modsi3 + EXPORT |__modsi3| + IMPORT |__div0| + + /* a1 = (a1 / a2) remainder a2 + returns remainder in a1 */ + +|__modsi3| + ANDS ip, a1, #&80000000 + RSBMI a1, a1, #0 + MOVS a2, a2 + BEQ |__div0| /* divide by zero. */ + RSBMI a2, a2, #0 + MOV a3, a2 + + CMP a3, a1, LSR #16 + MOVLS a3, a3, LSL #16 + CMP a3, a1, LSR #8 + MOVLS a3, a3, LSL #8 + CMP a3, a1, LSR #4 + MOVLS a3, a3, LSL #4 + CMP a3, a1, LSR #2 + MOVLS a3, a3, LSL #2 + CMP a3, a1, LSR #1 + MOVLS a3, a3, LSL #1 + +|__modsi3.divloop| + CMP a1, a3 + SUBCS a1, a1, a3 + MOV a3, a3, LSR #1 + CMP a3, a2 + BCS |__modsi3.divloop| + TST ip, #&80000000 + RSBNE a1, a1, #0 + RETURN(pc, lr) +#endif + +#ifdef L_muldi3 + EXPORT |__muldi3| + + /* (a1, a2) * (a3, a4) */ +|__muldi3| +#ifdef __ARM_ARCH_4__ + SMULL a1, a2, a3, a4 + RETURN(pc, lr) +#else + STMFD sp!, {v1, v2, v3, lr} + MOV v2, a1, LSR #16 + BIC ip, a1, v2, LSL #16 + MOV v1, a3, LSR #16 + BIC lr, a3, v1, LSL #16 + MUL v3, v2, v1 + MUL v2, lr, v2 + MUL v1, ip, v1 + MUL ip, lr, ip + ADDS lr, v2, v1 + ADDCS v3, v3, #&10000 + ADDS v1, ip, lr, LSL #16 + ADC v2, v3, lr, LSR #16 + MLA v2, a1, a4, v2 + MLA a2, a3, a2, v2 + MOV a1, v1 + LDMFD sp!, {v1, v2, v3, pc}RETCOND +#endif /* __ARM_ARCH_4__ */ +#endif /* L_muldi3 */ + +#ifdef L_ucmpdi2 + EXPORT |__ucmpdi2| + /* compare two unsigned long long ints + enter with __ucmpdi2 (DItype a, DItype b) + entry a1,a2 = u, a3,a4 = v + exit u > v = 2, u < v = 0, u = v = 1 */ +|__ucmpdi2| + CMP a2, a4 + CMPEQ a1, a3 + MOVCC a1, #0 + MOVHI a1, #2 + MOVEQ a1, #1 + RETURN(pc, lr) +#endif + +#ifdef L_udivdi3 + EXPORT |__udivdi3| + IMPORT |__div0| + +/* (a1, a2) / (a3, a4) + result in v2 and v3 + remainder in v4 and ip */ +|__udivdi3| + CMP a1, #0 + CMPEQ a2, #0 + RETURNc(eq, pc, lr) + CMP a3, #0 + CMPEQ a4, #0 + BEQ |__div0| /* divide by zero. */ + STMFD sp!, {v2, v3, v4, lr} + MOV v2, #0 + MOV v3, #0 + MOV v4, a1 + MOV ip, a2 + MOVS lr, #0 +|__udivdi3.bit_count| + ADDS a3, a3, a3 + ADCS a4, a4, a4 + BCS |__udivdi3.count_done| + CMP a4, ip + CMPEQ a3, v4 + ADDLS lr, lr, #1 + BLS |__udivdi3.bit_count| + ADDS lr, lr, #0 +|__udivdi3.count_done| + MOVS a4, a4, RRX + MOV a3, a3, RRX +|__udivdi3.division| + SUBS a1, v4, a3 + SBCS a2, ip, a4 + MOVCS v4, a1 + MOVCS ip, a2 + ADCS v2, v2, v2 + ADC v3, v3, v3 + MOVS a4, a4, LSR #1 + MOV a3, a3, RRX + SUBS lr, lr, #1 + BGE |__udivdi3.division| + MOV a1, v2 + MOV a2, v3 + LDMFD sp!, {v2, v3, v4, pc}RETCOND +#endif + +#ifdef L_udivsi3 + EXPORT |__udivsi3| + EXPORT |__udivmodsi4| + IMPORT |__div0| + +/* a1 = (a1 / a2) remainder a2 + returns quotient in a1 + returns remainder in a2 + + a1 = numerator + a2 = denominator + a1 = quotient + a2 = remainder + ip = temporary store */ + +|__udivsi3| +|__udivmodsi4| + MOV a3, a1 + MOVS ip, a2 + BEQ |__div0| /* divide by zero. */ + + CMP ip, a3, LSR #16 + MOVLS ip, ip, LSL #16 + CMP ip, a3, LSR #8 + MOVLS ip, ip, LSL #8 + CMP ip, a3, LSR #4 + MOVLS ip, ip, LSL #4 + CMP ip, a3, LSR #2 + MOVLS ip, ip, LSL #2 + CMP ip, a3, LSR #1 + MOVLS ip, ip, LSL #1 + + MOV a1, #0 +|__udivsi3.divloop| + CMP a3, ip + SUBCS a3, a3, ip + ADC a1, a1, a1 + MOV ip, ip, LSR #1 + CMP ip, a2 + BCS |__udivsi3.divloop| + MOV a2, a3 + RETURN(pc, lr) +#endif + +#ifdef L_umoddi3 + EXPORT |__umoddi3| + IMPORT |__div0| + + /* (a1, a2) / (a3, a4) + result in v2 and v3 + remainder in v4 and ip */ +|__umoddi3| + CMP a1, #0 + CMPEQ a2, #0 + RETURNc(eq, pc, lr) + CMP a3, #0 + CMPEQ a4, #0 + BEQ |__div0| /* divide by zero. */ + STMFD sp!, {v2, v3, v4, lr} + MOV v2, #0 + MOV v3, #0 + MOV v4, a1 + MOV ip, a2 + MOVS lr, #0 +|__umoddi3.bit_count| + ADDS a3, a3, a3 + ADCS a4, a4, a4 + BCS |__umoddi3.count_done| + CMP a4, ip + CMPEQ a3, v4 + ADDLS lr, lr, #1 + BLS |__umoddi3.bit_count| + ADDS lr, lr, #0 +|__umoddi3.count_done| + MOVS a4, a4, RRX + MOV a3, a3, RRX +|__umoddi3.division| + SUBS a1, v4, a3 + SBCS a2, ip, a4 + MOVCS v4, a1 + MOVCS ip, a2 + MOVS a4, a4, LSR #1 + MOV a3, a3, RRX + SUBS lr, lr, #1 + BGE |__umoddi3.division| + MOV a1, v4 + MOV a2, ip + LDMFD sp!, {v2, v3, v4, pc}RETCOND +#endif + +#ifdef L_umodsi3 + EXPORT |__umodsi3| + IMPORT |__div0| + +/* a1 = (a1 / a2) remainder a2 + returns remainder in a1 + + a1 = numerator + a2 = denominator + a1 = remainder + a3 = temporary store */ + + +|__umodsi3| + MOVS a3, a2 + BEQ |__div0| /* divide by zero */ + + CMP a3, a1, LSR #16 + MOVLS a3, a3, LSL #16 + CMP a3, a1, LSR #8 + MOVLS a3, a3, LSL #8 + CMP a3, a1, LSR #4 + MOVLS a3, a3, LSL #4 + CMP a3, a1, LSR #2 + MOVLS a3, a3, LSL #2 + CMP a3, a1, LSR #1 + MOVLS a3, a3, LSL #1 + +|__umodsi3.divloop| + CMP a1, a3 + SUBCS a1, a1, a3 + MOV a3, a3, LSR #1 + CMP a3, a2 + BCS |__umodsi3.divloop| + MOV a1, a1 + RETURN(pc, lr) +#endif + +#ifdef L_div0 + /* Division by zero handler for RISC OS. */ + EXPORT |__div0| + IMPORT raise +|__div0| + stmfd sp!, {a1, a2, lr} +#ifdef TARGET_SCL + mov a1, #2 /* SIGFPE under the SharedCLibrary. */ +#else + mov a1, #8 /* SIGFPE under UnixLib. */ +#endif + bl raise + ldmfd sp!, {a1, a2, pc}RETCOND +#endif + +#ifdef L_ctors +/* This is a linker file used to help in the calling of constructors + and destructors. + + As the linker sorts areas alphabetically, and GCC uses a '2' postfix + on the constructor/destructor areas, we end up with: + + ; constructor code + ___CTOR__LIST__ + dcd -1 + dcd constructor list * + dcd 0 + + ; destructor code + ___DTOR_LIST__ + dcd -1 + dcd destructor list * + dcd 0 + + Note that as we use '0', '2' and '4' as postfixes, it is possible + to sneak in areas with postfixes of '1' and '3', if you want to + get clever. */ + + + AREA |C$$gnu_ctorsvec0|, DATA, READONLY + EXPORT |__CTOR_LIST__| +|__CTOR_LIST__| + DCD -1 + + AREA |C$$gnu_ctorsvec4|, DATA, READONLY + DCD 0 + + AREA |C$$gnu_dtorsvec0|, DATA, READONLY + EXPORT |__DTOR_LIST__| +|__DTOR_LIST__| + DCD -1 + + AREA |C$$gnu_dtorsvec4|, DATA, READONLY + DCD 0 +#endif + +#ifdef L_builtin_next_arg + /* Yep, mate it's a dummy function alright. */ + AREA |C$$code|, CODE, READONLY + + EXPORT |__builtin_next_arg| +|__builtin_next_arg| + RETURN(pc, lr) +#endif + + +#ifdef L_arm_alloca + +/* This file contains support routines for the use with the ARM Procedure +Call Standard and explicit stack check targets. + +Functions provided are: + __builtin_alloca + setjmp, longjmp + __builtin_return_address + __builtin_frame_address + __unwind_function + + +History: + Originally the alloca function should allocate space directly from the + run-time stack. + + Using a method like this would mean creating a new stack frame for + each dynamic alloca. It was deemed unsuitable because access to local + variables was very difficult, stack extension code was very slow and + the prospect of actually freeing the memory was further compilcated + with the need to directly access the stack frame in order to create + a suitable return address. In short, an extra 16 inlined instructions + were needed for each dynamic alloca call. The idea of nested functions, + C++ exception handling and various other minor details basically + destroyed any hope of this idea. + +Implementation: + The code below implements dynamic alloca and C++ exception handling + using five functions which are called in the necessary place by the + GNU compiler. + + For the following description, assume that when we refer to alloca + we mean an inlined dynamic allocation off the stack + + The emulation of alloca starts with a call to __arm_alloca_alloc. + This function uses malloc to claim the necessary memory and also + modifies the stack frame to call the function __arm_alloca_free_all + on exit from the function using alloca. Multiple calls to + __arm_alloca_alloc do not keep modifying the stack frame return address. + + To cope with different scopes, we assign a level number to each + alloca chunk. As the chunks leave scope, those chunks are removed. + To cope with goto's to different scopes, higher level chunks are also + removed. On exit from the function, __arm_alloca_free_all will be called + to remove any chunks not previously removed by calls to + __arm_alloca_block_free and also any chunks defined at the lowest scope + level of the function. + + For example: + + int foo (int x) + { + char *aaaa[x]; ; level 0 + char *aaab[x]; + { + char *baaa[x]; ; level 1 + char *baab[x]; + { + char *caaa[x]; ; level 2 + return 0; ; Will call _block_free with level = 2 and then + ; exit the function which will call _free_all, thus + ; removing the allocas at level 0 and 1. + } ; _block_free called with level = 2 + } ; _block_free called with level = 1 + } ; _block_free called with level = 0 + + + As a direct consequence of this technique, setjmp and longjmp must + be intercepted to avoid memory leakages from the dynamic allocation + routines. + + When setjmp is called, the current pointer to the list of dynamic + allocations is saved at the end of the jmp_buf. This is safe, because + gcc defines a macro to set the size of the jmp_buf (__JMP_BUF_SIZE). + Any header file defining the jmp_buf size needs to use this macro + otherwise the use of setjmp/longjmp will undoubtedly result in the + program crashing. + + When longjmp is called, all the dynamic allocations made since the + previous setjmp with the same buffer are freed. If the value stored + in the jmp_buf is not found during the freeing of the dynamic + allocations then the longjmp wrapper routine will abort. + + A previous implementation used a separately allocated area of memory + to save the linkage between the jmp_buf and the state of dynamic + allocation. This method had extremely bad run-time performance and + had a memory leak with this saved linkage information persisting + not being deallocated (not possible without more hacks to the main + compiler). + + Additionally, if threads are in use then the list of chunks is stored + on a per-thread basis, and ___arm_alloca_thread_free_all is called + when the thread exits, to ensure all allocations for that thread get + released. */ + +/* Version 2.13 (06 Nov 1999) */ + +XOS_Write0 * &20002 + + [ __FEATURE_PTHREADS = 0 + ; When pthreads are in use this is stored per-thread + AREA |C$$data|, DATA + ALIGN 4 + EXPORT |__arm_alloca_st| + /* If you change this then make sure you change the references + to it in arm.md (save_block_stack, save_stack_nonlocal). */ +|__arm_alloca_st| + DCD 0 /* unsigned int level */ + DCD 0 /* chunk *list */ + ] + +/* Structures used within this source: + +typedef struct __chunk { + void *frame_pointer + unsigned int level + struct __chunk *prev_chunk + void *return_address +} chunk + +struct __arm_alloca_st { + unsigned int level + chunk *list +} */ + + + /* offsets for fields of chunk struct, change at your peril + because some uses of ldm,stm rely on this ordering */ +chunks_fp_off * 0 +chunks_level_off * 4 +chunks_prev_off * 8 +chunks_retaddr_off * 12 + +chunk_size * 16 + + /* offsets for fields of alloca_list struct, change at your peril + because some uses of ldm,stm rely on this ordering */ +level_off * 0 +list_off * 4 + + /* UnixLib's jmp_buf is 26 words, Norcroft's is 22 words + so gcc's is 27 (one more word than the biggest) + setjmp_save is the offset to the 25th word. */ +setjmp_save * (26*4) + + + AREA |C$$code|, CODE, READONLY + + ALIGN 4 + [ __FEATURE_PTHREADS = 0 +|arm_alloca_ptr| + DCD |__arm_alloca_st| + ] + + /* please ensure all routines are preceded by their own + register usage. While ObjASM will complain if the same + name is used for different register numbers, doing this + helps prevent double use of a register by mistake. + Each routine should be able to fed independently through + ObjASM to verify this. */ + + /* ----------------------------------------------------------------- + ___arm_alloca_free_all + + register usage */ +arm_alloca_v RN 5 +alloca_level RN 6 +old_chunks RN 7 +return_addr RN 8 +chunks RN 9 + + /* scratch register usage */ +chunks_fp_a RN 2 +chunks_level_a RN 3 +chunks_retaddr_a RN 12 + + /* check offsets to fields tie up with ldm/stm register usage */ +#if 0 + [ chunks_fp_off < chunks_level_off + ASSERT chunks_fp_a < chunks_level_a + | + ASSERT chunks_fp_a > chunks_level_a + ] + [ chunks_fp_off < chunks_prev_off + ASSERT chunks_fp_a < chunks + | + ASSERT chunks_fp_a > chunks + ] + [ chunks_fp_off < chunks_retaddr_off + ASSERT chunks_fp_a < chunks_retaddr_a + | + ASSERT chunks_fp_a > chunks_retaddr_a + ] + [ chunks_level_off < chunks_prev_off + ASSERT chunks_level_a < chunks + | + ASSERT chunks_level_a > chunks + ] + [ chunks_level_off < chunks_retaddr_off + ASSERT chunks_level_a < chunks_retaddr_a + | + ASSERT chunks_level_a > chunks_retaddr_a + ] + [ chunks_prev_off < chunks_retaddr_off + ASSERT chunks < chunks_retaddr_a + | + ASSERT chunks > chunks_retaddr_a + ] + + [ list_off > level_off + ASSERT alloca_level < chunks + | + ASSERT alloca_level > chunks + ] +#endif + + IMPORT |free| + IMPORT |abort| + IMPORT |__pthread_running_thread| + + ALIGN 4 +|___arm_alloca_free_all| + STMFD sp!, {a1, a2, a3, a4, arm_alloca_v, chunks, old_chunks, return_addr, alloca_level, fp, ip} + [ __FEATURE_PTHREADS = 1 + LDR arm_alloca_v, =|__pthread_running_thread| + LDR arm_alloca_v, [arm_alloca_v] + ADD arm_alloca_v, arm_alloca_v, #__PTHREAD_ALLOCA_OFFSET + | + LDR arm_alloca_v, [pc, #|arm_alloca_ptr| - . -8] + ] + MOV return_addr, #0 + + /* alloca_level = arm_alloca.level; chunks = arm_allocal.list; */ + LDMIA arm_alloca_v, {alloca_level,chunks} + MOV old_chunks, #0 +|L..17| /* while (chunks != NULL) { */ + MOVS a1, chunks /* temp = chunks; */ + BEQ |L..3| + LDMIA chunks, {chunks_fp_a,chunks_level_a,chunks,chunks_retaddr_a} + CMP chunks_fp_a, fp /* if (chunks->frame_pointer == frame_p) { */ + BNE |L..5| + + /* Free this chunk since the frame pointers match up. */ + CMP chunks_level_a, alloca_level + MOVCC alloca_level, chunks_level_a + + /* If the return address is set then record it prior to freeing this chunk */ + CMP chunks_retaddr_a, #0 + MOVNE return_addr, chunks_retaddr_a + CMP old_chunks, #0 + STRNE chunks, [old_chunks, #chunks_prev_off] + BL |free| + + /* If the return address has been found, then break out of the loop now. */ + CMP return_addr, #0 + BNE |L..3| + B |L..17| +|L..5| + CMP old_chunks, #0 + STREQ a1, [arm_alloca_v, #list_off] + MOV old_chunks, a1 + B |L..17| +|L..3| + CMP old_chunks, #0 + /* if (old_chunks == NULL) arm_alloca.list = chunks */ + STREQ chunks, [arm_alloca_v, #list_off] + LDRNE chunks, [arm_alloca_v, #list_off] + + /* If the list is now empty, then the level can be reset to zero */ + CMP chunks, #0 + STREQ chunks, [arm_alloca_v, #level_off] + STRNE alloca_level, [arm_alloca_v, #level_off] + + /* We are in serious trouble if there is no return address, so abort. */ + CMP return_addr, #0 + ADREQ a1, |dynamic_alloca_rtn_error| + SWIEQ XOS_Write0 + BLEQ |abort| + MOV lr, return_addr + LDMFD sp!, {a1, a2, a3, a4, arm_alloca_v, chunks, old_chunks, return_addr, alloca_level, fp, ip} + RETURN(pc, lr) + +|dynamic_alloca_rtn_error| + DCB "Dynamic alloca return point corrupted", 13, 10 + DCB 0 + ALIGN + + + /* ----------------------------------------------------------------- + ___arm_alloca_thread_free_all + + register usage */ +/* +arm_alloca_v RN 5 +chunks RN 9 +*/ + + IMPORT |free| + IMPORT |__pthread_running_thread| + + ALIGN 4 + EXPORT |___arm_alloca_thread_free_all| +|___arm_alloca_thread_free_all| + STMFD sp!, {arm_alloca_v, chunks, lr} + [ __FEATURE_PTHREADS = 1 + LDR arm_alloca_v, =|__pthread_running_thread| + LDR arm_alloca_v, [arm_alloca_v] + ADD arm_alloca_v, arm_alloca_v, #__PTHREAD_ALLOCA_OFFSET + | + LDR arm_alloca_v, [pc, #|arm_alloca_ptr| - . -8] + ] + + LDR chunks, [arm_alloca_v, #list_off] + MOV a1, #0 + STR a1, [arm_alloca_v, #list_off] + STR a1, [arm_alloca_v, #level_off] +|L..18| /* while (chunks != NULL) { */ + MOVS a1, chunks /* temp = chunks; */ + LDMEQFD sp!, {arm_alloca_v, chunks, pc}RETCOND + LDR chunks, [chunks, #chunks_prev_off] + + BL |free| + B |L..18| + + + /* ----------------------------------------------------------------- + ___arm_alloca_alloc + + register usage */ +buffer RN 0 /* do not change this register */ +arm_alloca_a RN 1 +gbaa_t1 RN 2 /* temp registers */ +gbaa_t2 RN 3 +gbaa_t3 RN 12 + + /* check scratch registers are consistent for ldm/stm usage */ +#if 0 + ASSERT gbaa_t1 <> gbaa_t2 + ASSERT gbaa_t1 <> gbaa_t3 + ASSERT gbaa_t2 <> gbaa_t3 + ASSERT gbaa_t1 = chunks_fp_a + ASSERT gbaa_t2 = chunks_level_a + + [ list_off > level_off + ASSERT gbaa_t3 > gbaa_t2 + | + ASSERT gbaa_t3 < gbaa_t2 + ] +#endif + + IMPORT |malloc| + IMPORT |abort| + + ALIGN 4 + EXPORT |___arm_alloca_alloc| +|___arm_alloca_alloc| + /* Allocating nothing ? Then just return. */ + CMP a1, #0 + RETURNc(eq, pc, lr) + STMFD sp!, {lr} + ADD a1, a1, #chunk_size + BL malloc + + /* If we could not malloc any space then print an error message + and force an abort. */ + CMP buffer, #0 + ADREQ a1, |dynamic_alloca_error| + SWIEQ XOS_Write0 + BLEQ abort /* abort never returns */ + + /* get pointer to chunk list and level number */ + [ __FEATURE_PTHREADS = 1 + LDR arm_alloca_a, =|__pthread_running_thread| + LDR arm_alloca_a, [arm_alloca_a] + ADD arm_alloca_a, arm_alloca_a, #__PTHREAD_ALLOCA_OFFSET + | + LDR arm_alloca_a, [pc, #|arm_alloca_ptr|-.-8] + ] + LDMIA arm_alloca_a, {gbaa_t2,gbaa_t3} + + /* store the frame pointer, chunk list ptr and level number + in the memory we've just allocated. */ + LDR gbaa_t1, [fp, #-12] + STMIA buffer, {gbaa_t1,gbaa_t2,gbaa_t3} /* set fp, level, prev */ + + /* Get proper frame return address and store it in the return_address + field in our __chunk structure. If not already done so, + set the return address of the frame to __arm_alloca_free_all. */ + LDR gbaa_t2, [fp, #-4] + [ {CONFIG} = 26 + BIC gbaa_t1, gbaa_t2, #&FC000003 + | + MOV gbaa_t1, gbaa_t2 + ] + ADR gbaa_t3, |___arm_alloca_free_all| + CMP gbaa_t1, gbaa_t3 + MOVEQ gbaa_t2, #0 + STR gbaa_t2, [buffer, #chunks_retaddr_off] + STR buffer, [arm_alloca_a, #list_off] + STRNE gbaa_t3, [fp, #-4] + ADD buffer, buffer, #chunk_size + LDMFD sp!, {pc}RETCOND + +|dynamic_alloca_error| + DCB "Not enough free memory for dynamic alloca", 13, 10 + DCB 0 + ALIGN + + /* ----------------------------------------------------------------- + ___arm_alloca_block_free + + register usage */ +lev RN 4 +all_allocations_freed RN 6 + +/* +;arm_alloca_v RN v2 +;old_chunks RN v4 +;return_addr RN v5 +;chunks RN v6 + + ; scratch register usage +;chunks_fp_a RN a3 +;chunks_level_a RN a4 +;chunks_retaddr_a RN ip +*/ + IMPORT |free| + + ALIGN + EXPORT |___arm_alloca_block_free| +|___arm_alloca_block_free| + STMFD sp!, {lev, chunks, arm_alloca_v, old_chunks, return_addr, all_allocations_freed, fp, ip, lr} + MOV lev, a1 + MOV return_addr, #0 + [ __FEATURE_PTHREADS = 1 + LDR arm_alloca_v, =|__pthread_running_thread| ; should be conditional on __FEATURE_PTHREADS + LDR arm_alloca_v, [arm_alloca_v] + ADD arm_alloca_v, arm_alloca_v, #__PTHREAD_ALLOCA_OFFSET + | + LDR arm_alloca_v, [pc, #|arm_alloca_ptr|-.-8] + ] + MOV all_allocations_freed, #1 + LDR chunks, [arm_alloca_v, #list_off] + MOV old_chunks, #0 +|L..42| + /* while (chunks != NULL) */ + MOVS a1, chunks + BEQ |L..27| + LDMIA chunks, {chunks_fp_a,chunks_level_a,chunks,chunks_retaddr_a} + + /* if (chunks->level >= lev) */ + CMP chunks_level_a, lev + BCC |L..29| + + /* If the return address is set then record it prior to freeing this chunk */ + CMP chunks_retaddr_a, #0 + MOVNE return_addr, chunks_retaddr_a + + /* Remove this entry from the list */ + CMP old_chunks, #0 + STRNE chunks, [old_chunks, #chunks_prev_off] + BL |free| + + /* If the return address has been found, then break out of the loop now. */ + CMP return_addr, #0 + BNE |L..27| + B |L..42| +|L..29| + /* Record that we haven't freed all the alloc space for this function. + Note, this check is specific to block_free. */ + CMP chunks_fp_a, fp + MOVEQ all_allocations_freed, #0 + + /* No chunk was freed so point old_chuks to that chunk */ + CMP old_chunks, #0 + STREQ a1, [arm_alloca_v, #list_off] + MOV old_chunks, a1 + B |L..42| +|L..27| + /* if (old_chunks == NULL) */ + CMP old_chunks, #0 + STREQ chunks, [arm_alloca_v, #list_off] + + /* following optimisation using a1,a2 is valid providing asserts hold */ +#if 0 + ASSERT level_off = 0 + ASSERT list_off = 4 +#endif + /* if the list is now empty, then the level can be reset to zero. */ + LDMIA arm_alloca_v, {a1, a2} /* level, list */ + CMP a2, #0 + MOVEQ a1, #0 + BEQ |L..39| + /* else if (arm_alloca.level >= lev) */ + CMP a1, lev + SUBCS a1, lev, #1 +|L..39| + STR a1, [arm_alloca_v, #level_off] + /* Unpatch return address on the stack. */ + CMP return_addr, #0 + CMPNE all_allocations_freed, #0 + STRNE return_addr, [fp, #-4] + LDMFD sp!, {lev, chunks, arm_alloca_v, old_chunks, return_addr, all_allocations_freed, fp, ip, pc}RETCOND + + /* ----------------------------------------------------------------- + ___arm_alloca_block_init + + register usage */ +/* ;arm_alloca_a RN a2 */ + + ALIGN 4 + EXPORT |___arm_alloca_block_init| +|___arm_alloca_block_init| + [ __FEATURE_PTHREADS = 1 + LDR arm_alloca_a, =|__pthread_running_thread| + LDR arm_alloca_a, [arm_alloca_a] + ADD arm_alloca_a, arm_alloca_a, #__PTHREAD_ALLOCA_OFFSET + | + LDR arm_alloca_a, [pc, #|arm_alloca_ptr|-.-8] + ] + LDR a1, [arm_alloca_a, #level_off] + ADD a1, a1, #1 + STR a1, [arm_alloca_a, #level_off] + RETURN(pc, lr) + + /* ----------------------------------------------------------------- + ___arm_alloca_setjmp + + register usage */ +/* ;arm_alloca_a RN a2 */ + + IMPORT |setjmp| + + ALIGN 4 + EXPORT |___arm_alloca_setjmp| +|___arm_alloca_setjmp| + /* Store within the setjmp buffer a pointer to the linked + list of alloca chunks. longjmp will use this to free any + memory allocated with `alloca' between the setjmp and longjmp */ + [ __FEATURE_PTHREADS = 1 + LDR arm_alloca_a, =|__pthread_running_thread| ; should be conditional on __FEATURE_PTHREADS + LDR arm_alloca_a, [arm_alloca_a] + ADD arm_alloca_a, arm_alloca_a, #__PTHREAD_ALLOCA_OFFSET + | + LDR arm_alloca_a, [pc, #|arm_alloca_ptr|-.-8] + ] + LDR a4, [arm_alloca_a, #list_off] + STR a4, [a1, #setjmp_save] + B |setjmp| + + /* ----------------------------------------------------------------- + ___arm_alloca_longjmp + + register usage */ +num_save RN 4 +search_value RN 7 +jmpbuf RN 8 +/* ;arm_alloca_v RN v2 +;chunks RN v6 */ + + IMPORT |abort| + IMPORT |free| + IMPORT |longjmp| + + ALIGN 4 + EXPORT |___arm_alloca_longjmp| +|___arm_alloca_longjmp| + MOV jmpbuf, a1 + MOV num_save, a2 + [ __FEATURE_PTHREADS = 1 + LDR arm_alloca_v, =|__pthread_running_thread| + LDR arm_alloca_v, [arm_alloca_v] + ADD arm_alloca_v, arm_alloca_v, #__PTHREAD_ALLOCA_OFFSET + | + LDR arm_alloca_v, [pc, #|arm_alloca_ptr|-.-8] + ] + LDR chunks, [arm_alloca_v, #list_off] + LDR search_value, [jmpbuf, #setjmp_save] + B |L..48| +|L..49| + MOV a1, chunks + LDR chunks, [chunks, #chunks_prev_off] + STR chunks, [arm_alloca_v, #list_off] + STR chunks, [jmpbuf, #setjmp_save] + BL |free| +|L..48| + CMP chunks, search_value + CMPNE chunks, #0 + BNE |L..49| + /* Something must be wrong if we have hit the end of the list + and not found the list pointer stored in the jmp_buf. + Probably calling longjmp with an undefined value */ + /* CMP chunks, search_value + ADRNE a1, |arm_alloca_longjmp_error| + SWINE XOS_Write0 + BNE |abort| */ +|L..51| + /* Call longjmp with the proper values. */ + MOV a1, jmpbuf + MOV a2, num_save + B |longjmp| + +|arm_alloca_longjmp_error| + DCB "longjmp error: longjmp probably called with an undefined value", 13, 10 + DCB 0 + ALIGN + + /* ----------------------------------------------------------------- + ___arm_alloca_nonlocal_save + + register usage */ +/* ;arm_alloca_a RN a2 */ + + ALIGN 4 + EXPORT |___arm_alloca_nonlocal_save| +|___arm_alloca_nonlocal_save| + [ __FEATURE_PTHREADS = 1 + LDR arm_alloca_a, =|__pthread_running_thread| + LDR arm_alloca_a, [arm_alloca_a] + ADD arm_alloca_a, arm_alloca_a, #__PTHREAD_ALLOCA_OFFSET + | + LDR arm_alloca_a, [pc, #|arm_alloca_ptr|-.-8] + ] + LDR a1, [arm_alloca_a, #list_off] + RETURN(pc, lr) + + /* ----------------------------------------------------------------- + ___arm_alloca_nonlocal_restore + + register usage */ +/* ;search_value RN 7 */ +/* ;arm_alloca_v RN v2 +;chunks RN v6 */ + + IMPORT |abort| + IMPORT |free| + + ALIGN 4 + EXPORT |___arm_alloca_nonlocal_restore| +|___arm_alloca_nonlocal_restore| + STMFD sp!, {chunks, arm_alloca_v, search_value, fp, ip, lr} + MOV search_value, a1 + [ __FEATURE_PTHREADS = 1 + LDR arm_alloca_v, =|__pthread_running_thread| + LDR arm_alloca_v, [arm_alloca_v] + ADD arm_alloca_v, arm_alloca_v, #__PTHREAD_ALLOCA_OFFSET + | + LDR arm_alloca_v, [pc, #|arm_alloca_ptr|-.-8] + ] + LDR chunks, [arm_alloca_v, #list_off] + B |L..48.1| +|L..49.1| + MOV a1, chunks + LDR chunks, [chunks, #chunks_prev_off] + STR chunks, [arm_alloca_v, #list_off] + BL |free| +|L..48.1| + CMP chunks, search_value + CMPNE chunks, #0 + BNE |L..49.1| + /* Something must be wrong if we have hit the end of the list + and not found the list pointer stored in the jmp_buf. + Probably calling nonlocal_restore with an undefined value */ + CMP chunks, search_value + LDMEQFD sp!, {chunks, arm_alloca_v, search_value, fp, ip, pc}RETCOND + ADR a1, |arm_alloca_nonlocal_restore_error| + SWI XOS_Write0 + B |abort| + +|arm_alloca_nonlocal_restore_error| + DCB "error: nonlocal_restore probably called with an undefined value", 13, 10 + DCB 0 + ALIGN + + /* ----------------------------------------------------------------- + __builtin_return_address + + return the return address from 'frames' functions ago. */ + EXPORT |__builtin_return_address| +|__builtin_return_address| + STMFD sp!, {lr} + BL |__builtin_frame_address| + LDR a1, [a1, #-4] + LDMFD sp!, {pc}RETCOND + + /* ----------------------------------------------------------------- + __builtin_frame_address + + return the address of the frame 'count' functions ago */ + +/* +typedef struct __exception_stack_chunk +{ + unsigned long sc_mark; == 0xf60690ff + struct __exception_stack_chunk *sc_next, *sc_prev; + unsigned long sc_size; + int (*sc_deallocate)(void *); +} _exception_stack_chunk; + +A UnixLib chunked stack is the same as above, but with an additional +word at the end holding the return address after the chunk is freed. +It is 536 bytes below sl, whereas for the scl it is 560 bytes below sl. +*/ + +reg_fp RN 0 +sc RN 1 +x RN 2 +frames RN 3 +bra_t1 RN 4 +bra_marker RN 5 +next_fp RN 12 + + EXPORT |__builtin_frame_address| +|__builtin_frame_address| + MOV ip, sp + STMFD sp!, {bra_t1, bra_marker, fp, ip, lr, pc} + SUB fp, ip, #4 + + MOV frames, a1 + /* Get previous fp value. If zero, we have no enclosing frame, + so no return address. */ + LDR a1, [fp, #-12] + CMP a1, #0 + /* No enclosing frame, so no return address. */ + LDMEQEA fp, {bra_t1, bra_marker, fp, sp, pc}RETCOND + MOV reg_fp, fp + /* We must cope with a variety of UnixLib and SharedCLibrary stacks + occuring within a program. */ + LDR bra_marker, =&F60690FF + /* Make 'sc' point to the current stack chunk. */ + SUB sc, sl, #536 /* check for UnixLib chunked stack */ + LDR bra_t1, [sc, #0] /* sc->sc_mark */ + CMP bra_t1, bra_marker + /* If not a UnixLib chunked stack, then it must be a + SharedCLibrary chunked stack or it is not chunked */ + SUBNE sc, sl, #560 + MOV x, #0 +|__builtin_frame_address.loop| + + LDR next_fp, [reg_fp, #-12] + LDR bra_t1, [sc, #0] /* sc->sc_mark */ + CMP bra_marker, bra_t1 + MOVNE reg_fp, next_fp + BNE |__builtin_frame_address.loop.end| + + LDR bra_t1, [sc, #12] /* sc->sc_size */ + ADD bra_t1, bra_t1, sc /* sc_limit = sc+sc->sc_size */ + CMP next_fp, bra_t1 /* next_fp >= sc_limit */ + BGE |__builtin_frame_address.shared.c.library| + + CMP next_fp, sc + MOVGE reg_fp, next_fp + BGE |__builtin_frame_address.loop.end| + + /* SharedCLibrary style: Current frame is outside current stack + chunk, so current frame's stack is the first in this chunk + and was created via stack extension. */ +|__builtin_frame_address.shared.c.library| + LDR sc, [sc, #8] /* sc->sc_prev */ + CMP sc, #0 /* No previous stack chunk */ + MOVEQ a1, #0 + LDMEQEA fp, {bra_t1, bra_marker, fp, sp, pc}RETCOND + LDR reg_fp, [next_fp, #-12] + +|__builtin_frame_address.loop.end| + ADD x, x, #1 + CMP x, frames + BLE |__builtin_frame_address.loop| + + + LDR bra_t1, [sc, #0] + CMP bra_t1, bra_marker /* sc->sc_mark == 0xf60690ff */ + /*; MOVNE a1, reg_fp. If reg_fp != a1 then we need this instruction */ + LDMNEEA fp, {bra_t1, bra_marker, fp, sp, pc}RETCOND + + LDR bra_t1, [sc, #12] + ADD bra_t1, bra_t1, sc ; sc+sc->sc_size + CMP reg_fp, bra_t1 + LDRGE a1, [reg_fp, #-12] + LDMGEEA fp, {bra_t1, bra_marker, fp, sp, pc}RETCOND + + CMP reg_fp, sc + LDRLT reg_fp, [reg_fp, #-12] + /* MOV a1, reg_fp. If reg_fp != a1 then we need this instruction */ + + LDMEA fp, {bra_t1, bra_marker, fp, sp, pc}RETCOND + + /* ----------------------------------------------------------------- + __unwind_function + + unwinds the stack by one level, effectively making the stack of + the parent function available. */ + +uf_t1 RN 0 +temp_lr RN 2 +/* ;sc RN 1 +;next_fp RN 12 */ + + EXPORT |__unwind_function| +|__unwind_function| + MOV temp_lr, lr + LDR a1, [fp, #-12] + CMP a1, #0 + BLEQ |abort| /* no enclosing frame, so no previous stack */ + /* MOV reg_fp, fp */ + + LDR uf_t1, =&F60690FF + SUB sc, sl, #536 /* check for UnixLib chunked stack */ + LDR next_fp, [sc, #0] /* sc->sc_mark */ /* use next_fp as a temp. reg here */ + CMP next_fp, bra_marker + /* If not a UnixLib chunked stack, then it must be a + SharedCLibrary chunked stack or it is not chunked */ + SUBNE sc, sl, #560 + LDR next_fp, [sc, #0] /* use next_fp as a temp. reg here */ + CMP next_fp, uf_t1 /* sc->sc_mark == 0xf60690ff */ + LDMNEEA fp, {fp, sp, lr} /* unwind stack one level and exit */ + RETURNc(ne, pc, temp_lr) + + LDR next_fp, [fp, #-12] + LDR uf_t1, [sc, #12] /* sc->sc_size */ + ADD uf_t1, uf_t1, sc + CMP next_fp, uf_t1 + BGE |__unwind_function.shared.c.library| + + CMP next_fp, sc + LDMGEEA fp, {fp, sp, lr} /* unwind stack one level and exit */ + RETURNc(ge, pc, temp_lr) +|__unwind_function.shared.c.library| + ; Shared C Library style stack chunk + LDR uf_t1, [sc, #8] /* sc->sc_prev */ + CMP uf_t1, #0 + BLEQ |abort| /* no previous stack chunk */ + /* Move to previous stack chunk, free the current one, + and remove the pointer to the next stack chunk in the + previous stack chunk. */ + MOV a1, #0 + STR a1, [sc, #4] /* sc->sc_next = 0 */ + MOV a1, sc + LDR sc, [sc, #8] + STMFD sp!, {sc, temp_lr, next_fp} + MOV lr, pc + LDR pc, [a1, #16] /* sc_deallocate (sc) */ + LDMFD sp!, {sc, temp_lr, next_fp} + LDMEA next_fp, {fp, sp, lr} + ADD sl, sc, #560 + RETURN(pc, temp_lr) +#endif + + END + Index: gcc/config/arm/libgcc_fix.s =================================================================== RCS file: gcc/config/arm/libgcc_fix.s diff -N gcc/config/arm/libgcc_fix.s --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ gcc/config/arm/libgcc_fix.s 8 Feb 2005 01:20:34 -0000 1.1 @@ -0,0 +1,41 @@ +/* ARM/RISC OS declarations to prevent some undefined symbol warnings +in the link phase for GNU compiler. +Copyright (C) 1996 Free Software Foundation, Inc. +Contributed by Nick Burrett (n.a.burrett@mcs.salford.ac.uk) + +This file is part of GNU CC. + +GNU CC 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. + +GNU CC 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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. + +As a special exception, if you link this library with other files, +some of which are compiled with GCC, to produce an executable, +this library does not by itself cause the resulting executable +to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* Version 1.03 (09 May 1996) */ + + AREA |C$$code|, CODE, READONLY + + EXPORT |_exit_dummy_decl| + /* Referenced in libgcc2.c but never declared there for our + particular configuration. */ +|_exit_dummy_decl| + DCD 0 + + + END Index: gcc/config/arm/riscos-aof.h =================================================================== RCS file: gcc/config/arm/riscos-aof.h diff -N gcc/config/arm/riscos-aof.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ gcc/config/arm/riscos-aof.h 20 Feb 2005 20:16:13 -0000 1.4 @@ -0,0 +1,293 @@ +/* Operating system specific defines when targetting GCC for RISC OS. + Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + Contributed by Nick Burrett (nick.burrett@btinternet.com) + +This file is part of GNU CC. + +GNU CC 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. + +GNU CC 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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* This overrides all the paths that cpp attempts to use, as otherwise we + need to specifiy the same path several times. */ + +/* Structure format: directory name, for C++ only, C++ aware. */ + +#define INCLUDE_DEFAULTS \ +{ \ + { GCC_INCLUDE_DIR, "GCC", 0, 1}, \ + { GXX_INCLUDE_DIR, "G++", 1, 1}, \ + { SYSTEM_INCLUDE_DIR, 0, 0, 1}, \ + { 0, 0, 0, 0 } \ +} + +#define PATH_SEPARATOR ',' + +/* Descriptions for the assembler output format. */ + +/* This is used in ASM_FILE_START. */ +#define ARM_OS_NAME "RISC OS" + +/* Stack overflow checking functions. */ +#define ARM_STKOVF_SPLIT_SMALL "__rt_stkovf_split_small" +#define ARM_STKOVF_SPLIT_BIG "__rt_stkovf_split_big" + + + +/* Run-time Target Specification. */ + +#define TARGET_VERSION \ + fputs (" (ARM/RISC OS)", stderr) + +/* Extra command line options supported by the RISC OS backend. */ + +/* Non-zero if we allow the argument pointer (fp) to be used by + the register allocator. Note this option is really only useful + when not targetting the APCS. */ +#define ARM_USE_AP (0x10000000) +#define TARGET_USE_AP (target_flags & ARM_USE_AP) + +/* Non-zero if we wish to format dependencies for Acorn's + Make Utility. */ +#define ARM_AMU (0x20000000) +#define TARGET_AMU (target_flags & ARM_AMU) + +/* Non-zero if we will allow a text editor to capture our errors. */ +#define ARM_THROWBACK (0x40000000) +#define TARGET_THROWBACK (target_flags & ARM_THROWBACK) + +/* Options not used in cc1 will have bit 31 set. */ + +#define SUBTARGET_SWITCHES \ + {"use-arg-pointer", ARM_USE_AP, \ + "Make fp (r11) available to the register allocator" }, \ + {"no-use-arg-pointer", -ARM_USE_AP, "" }, \ + {"throwback", ARM_THROWBACK, \ + "Send errors to a DDEUtils compatible text editor" }, \ + {"no-throwback", -ARM_THROWBACK, "" }, \ + {"amu", ARM_AMU, \ + "Format source dependencies for Acorn's Make Utility" }, \ + {"no-amu", -ARM_AMU, "" }, \ + {"libscl", 0x80000000, \ + "Compile with the SharedCLibrary headers" }, \ + {"unixlib", -0x80000000, \ + "Compile with the headers from UnixLib (default)" }, + +/* Default RISC OS options + - APCS + - explicit stack checks */ +#define TARGET_DEFAULT (ARM_FLAG_APCS_FRAME + ARM_FLAG_APCS_STACK + ARM_FLAG_APCS_32) + +/* Prevent FRAME_POINTER_REGNUM being clobbered in functions that call + alloca. */ +#define PREVENT_FP_CLOBBER (TARGET_APCS_STACK) + +/* If we're targeting explicit APCS stack checks, then force calls to + __builtin_return_address and __builtin_frame_address as library + function calls. */ +#define HAVE_BUILTIN_RETURN_ADDR_FUNC (TARGET_APCS_STACK) +#define HAVE_BUILTIN_FRAME_ADDR_FUNC (TARGET_APCS_STACK) + +#define SUBTARGET_OVERRIDE_OPTIONS \ +{ \ + if (write_symbols != NO_DEBUG) \ + warning ("-g under RISC OS does not give useful debugging data"); \ + /* Floating point tuning. ARM 6, ARM 7 and StrongARM were */ \ + /* released for RISC OS 3.5 and above and this included an */ \ + /* architecture 3 floating point emulator. */ \ + if (arm_is_strong || arm_is_6_or_7) \ + arm_fpu_arch = FP_SOFT3; \ +} + +#define SUBTARGET_CONDITIONAL_REGISTER_USAGE \ +{ \ + if (TARGET_USE_AP) \ + { \ + fixed_regs[11] = 0; \ + call_used_regs[11] = 0; \ + } \ +} + +/* Add support of long doubles. Undefine for better compatibility with + Norcroft C. + Keep undefined at the moment due to incompatibilities between + the various floating point emulators and some other stuff. */ +#undef ARM_LONG_DOUBLE_SUPPORT + + +/* Unsigned chars produces much better code than signed. */ +#define DEFAULT_SIGNED_CHAR 0 + +/* Some systems use __main in a way incompatible with its use in gcc, in + these cases use the macros NAME__MAIN to give a quoted symbol and + SYMBOL__MAIN to give the same symbol without quotes for an alternative + entry point. You must define both, or neither. */ +#define NAME__MAIN "__gccmain" +#define SYMBOL__MAIN __gccmain + +/* In RISC OS: + size_t is "unsigned int" + ptrdiff_t is "int" + wchar_t is "int". */ +#define SIZE_TYPE "unsigned int" +#define PTRDIFF_TYPE "int" +#define WCHAR_TYPE "int" + +/* Size in bits of the data type for wide characters. */ +#define WCHAR_TYPE_SIZE 32 +#define MAX_WCHAR_TYPE_SIZE 32 + +/* Override the normal default CPU. */ +#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm6 + +/* For AOF style output. */ +#include "arm/aof.h" + +/* This code handle the constructor/destructor tables required for C++. + It relies on a feature in the AOF linker that sorts areas in the object + file into alphabetical order. In the gcc library, we have two areas for + both the constructors and destructors, which are named so the linker + brackets the data tables with these areas, thus setting up the complete + tables. Easy ! */ + +#undef CTORS_SECTION_ASM_OP +#define CTORS_SECTION_ASM_OP "AREA\t|C$$gnu_ctorsvec2|, DATA, READONLY" +#undef DTORS_SECTION_ASM_OP +#define DTORS_SECTION_ASM_OP "AREA\t|C$$gnu_dtorsvec2|, DATA, READONLY" + +#undef CTOR_LIST_BEGIN +#undef CTOR_LIST_END +#undef DO_GLOBAL_CTORS_BODY +#undef DTOR_LIST_BEGIN +#undef DTOR_LIST_END +#undef DO_GLOBAL_DTORS_BODY + +/* Translation to find startup files. In RISC OS, everything + is in one library. */ +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "" + +#undef LIBGCC_SPEC +#undef LINK_LIBGCC_SPECIAL +#undef LINK_LIBGCC_SPECIAL_1 + +/* RISC OS has some fun default libraries. */ +#undef LIB_SPEC + +/* A C string constant that tells the GNU CC driver program options to + pass to CPP. It can also specify how to translate options you give + to GNU CC into options for GNU CC to pass to the CPP. */ +#undef CPP_SPEC + +/* Options to pass to the linker. */ +#undef LINK_SPEC +#define LINK_SPEC "%{!nostdlib:-L/libstdcxx:/}" + +#undef ASM_FINAL_SPEC +#define ASM_FINAL_SPEC "" + + +/* Look for UnixLib unless mlibscl is set, then look for SharedCLib + stubs. */ +#define LIB_SPEC "%{!nostdlib:%{!mlibscl:-lUnixLib:a.unixlib}%{mlibscl:-lCLib:a.scl}}" + +#define CPP_SPEC "%(cpp_cpu_arch) %(cpp_apcs_pc) %(cpp_float) \ + -D__JMP_BUF_SIZE=27 %{mlibscl:-D__TARGET_SCL__} \ + %{mamu:-MD !Depend}" + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Darm -Driscos -Asystem(riscos) -Acpu(arm) -Amachine(acorn)" + +/* Options to pass through to the assembler. */ +#undef ASM_SPEC +#define ASM_SPEC "%{mcpu=strongarm:-t SA110 -apcsfpv3} \ + %{mcpu=arm6:-t ARM6 -apcsfpv3} \ + %{mcpu=arm7:-t ARM7 -apcsfpv3} \ + %{mfp=3:-apcsfpv3} %{mfpe=3:-apcsfpv3} %{mapcs-32:-apcs32} \ + %{mthrowback:-throwback}" + +#undef ASM_OUTPUT_COMMON +#if 0 +#define ASM_OUTPUT_COMMON(STREAM,NAME,SIZE,ROUNDED) \ + (common_section (), \ + fprintf ((STREAM), "\tEXPORT\t"), \ + assemble_name ((STREAM), (NAME)), \ + fprintf ((STREAM), "\n\tAREA "), \ + assemble_name ((STREAM), (NAME)), \ + fprintf ((STREAM), ", DATA, COMMON\n\t%% %d\t%s size=%d\n", \ + (ROUNDED), ASM_COMMENT_START, SIZE), \ + aof_delete_import ((NAME))) +#else +#define ASM_OUTPUT_COMMON(STREAM,NAME,SIZE,ROUNDED) \ + (common_section (), \ + fprintf ((STREAM), "\tAREA |Common$$%s|, DATA, COMMON\n", \ + (NAME)), \ + assemble_name ((STREAM), (NAME)), \ + fprintf ((STREAM), "\n\t%% %d\t%s size=%d\n", \ + (ROUNDED), ASM_COMMENT_START, (SIZE)), \ + aof_delete_import ((NAME)), \ + fprintf ((STREAM), "\tEXPORT\t"), \ + assemble_name ((STREAM), (NAME)), \ + fputc ('\n', (STREAM))) +#endif + +/* This is how we tell the assembler that a symbol is weak. */ +#undef ASM_WEAKEN_LABEL + +#undef DOLLARS_IN_IDENTIFIERS +#define DOLLARS_IN_IDENTIFIERS 0 + +#undef MULTILIB_DEFAULTS +#define MULTILIB_DEFAULTS { "munixlib", "mapcs-32", "archv3" } + +/* The backend assembler used for RISC OS does not support debugging data + - this might change in the future (but don't bet on it). */ +#ifdef DBX_DEBUGGING_INFO +#undef DBX_DEBUGGING_INFO +#endif + +#ifdef DWARF2_DEBUGGING_INFO +#undef DWARF2_DEBUGGING_INFO +#endif + +#define DBX_REGISTER_NUMBER(REGNO) (REGNO) + +#undef INITIALIZE_TRAMPOLINE +#undef CLEAR_INSN_CACHE + +/* Emit RTL insns to initialize the variable parts of a trampoline. + FNADDR is an RTX for the address of the function's pure code. + CXT is an RTX for the static chain value for the function. */ +#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ +{ \ + rtx end_addr; \ + \ + emit_move_insn (gen_rtx_MEM (SImode, plus_constant ((TRAMP), 8)), \ + (CXT)); \ + emit_move_insn (gen_rtx_MEM (SImode, plus_constant ((TRAMP), 12)), \ + (FNADDR)); \ + /* Flush the instruction cache. */ \ + end_addr = memory_address (SImode, plus_constant ((TRAMP), 16)); \ + emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__clear_icache"), \ + 0, VOIDmode, 2, \ + memory_address (SImode, (TRAMP)), Pmode, \ + end_addr, Pmode); \ +} + +/* A C expression used to clear the instruction cache from address + BEG to address END. */ +#define CLEAR_INSN_CACHE(BEG, END) __clear_icache (BEG, END) Index: gcc/config/arm/riscos.c =================================================================== RCS file: gcc/config/arm/riscos.c diff -N gcc/config/arm/riscos.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ gcc/config/arm/riscos.c 8 Feb 2005 01:20:34 -0000 1.1 @@ -0,0 +1,264 @@ +/* Functions for RISC OS as target machine for GNU C compiler. + Copyright (C) 1997, 1999 Free Software Foundation, Inc. + Contributed by Nick Burrett (nick@dsvr.net) + +This file is part of GNU CC. + +GNU CC 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. + +GNU CC 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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + +#define OS_FSControl 0x29 + +/* The DDEUtils module SWI names and their equivalent numbers. */ +#define DDEUtils_ThrowbackStart 0x42587 +#define DDEUtils_ThrowbackSend 0x42588 +#define DDEUtils_ThrowbackEnd 0x42589 + +/* The DDEUtils module throwback error category codes. */ +#define THROWBACK_INFORMATION -1 +#define THROWBACK_WARNING 0 +#define THROWBACK_ERROR 1 +#define THROWBACK_SERIOUS_ERROR 2 + +/* The DDEUtils module throwback reason codes. */ +#define THROWBACK_REASON_PROCESSING 0 +#define THROWBACK_REASON_ERROR_DETAILS 1 +#define THROWBACK_REASON_INFO_DETAILS 2 + +/* The full canonicalised pathname of the current error file. */ +static char *arm_error_file = NULL; + +/* Unique reference number for current file. + Used to determine whether DDEUtils module needs telling we + have changed the error file. */ +static int arm_error_file_ref = -1; + +/* Control status of throwback, + -1 => no throwback possible + 0 => throwback uninitialised, + 1 => throwback initialised + */ +static int arm_throwback_started = 0; + +/* Initialise the DDEUtils module for throwback. */ +static void +arm_throwback_start (void) +{ + int regs[10]; + + if (!__os_swi (DDEUtils_ThrowbackStart, regs)) + { + atexit (arm_throwback_finish); + arm_throwback_started = 1; + } + else + arm_throwback_started = -1; +} + +/* Tell DDEUtils that we are processing a new file. + The DDE documentation is unclear, but does suggest that this + message should be sent if the filename changes. */ +static void +arm_throwback_new_file (fname) + char *fname; +{ + int regs[10]; + + regs[0] = THROWBACK_REASON_PROCESSING; + regs[2] = (int)fname; + if (__os_swi (DDEUtils_ThrowbackSend, regs)) + arm_throwback_started = -1; +} + + +/* Send details of a specific error to DDEUtils module. */ +static void +arm_throwback_error (fname, level, line_number, error) + char *fname; + int level; + int line_number; + char *error; +{ + int regs[10]; + + regs[0] = (level == THROWBACK_INFORMATION) + ? THROWBACK_REASON_INFO_DETAILS + : THROWBACK_REASON_ERROR_DETAILS; + regs[1] = 0; + regs[2] = (int)fname; + regs[3] = line_number; + regs[4] = (level == THROWBACK_INFORMATION) ? 0 : level; + regs[5] = (int)error; + if (__os_swi (DDEUtils_ThrowbackSend, regs)) + arm_throwback_started = -1; +} + +/* Tell DDEUtils that we have finished throwing errors. */ +void +arm_throwback_finish (void) +{ + int regs[10]; + + if (arm_throwback_started > 0) + __os_swi (DDEUtils_ThrowbackEnd, regs); + arm_throwback_started = 0; +} + +/* Convert from Unix name to RISC OS name and canonicalise the name + so that throwback knows the full pathname of the file. + Return the converted filename, stored in arm_error_file, or NULL. */ +static char * +riscos_canonicalise_filename (char *sname) +{ + char *s; + int regs[10]; + char filename[256]; + + /* It's possible that the filename will be in Unix format. + Convert it into RISC OS format. */ + s = __riscosify (sname, 0, 0, filename, sizeof (filename), NULL); + /* Filename translation failed, so return NULL. */ + if (s == NULL) + return NULL; + + /* The first call will calculate the size of buffer needed to + store the canonicalised filename. */ + regs[0] = 37; + regs[1] = (int)filename; + regs[2] = 0; + regs[3] = 0; + regs[4] = 0; + regs[5] = 0; + if (!__os_swi (OS_FSControl, regs) && regs[5] < 0) + { + if ((arm_error_file = realloc (arm_error_file, 1 - regs[5])) != NULL) + { + /* Now perform the canonicalisation and store in a buffer + which we know is large enough. */ + regs[1] = (int)filename; + regs[2] = (int)arm_error_file; + regs[3] = 0; + regs[4] = 0; + regs[5] = 1 - regs[5]; + if (!__os_swi (OS_FSControl, regs) && regs[5] == 1) + return arm_error_file; + } + } + + /* Canonicalisation failed, so free arm_error_file and set it to null. */ + free (arm_error_file); + arm_error_file = NULL; + return NULL; +} + +/* Throwback interface to GNU C family of compilers. */ +void +arm_error_throwback (file, line, prefix, s, ap) + char *file; + int line; + char *prefix; + char *s; + va_list ap; +{ + /* If the filename is not specified or "", then return. */ + if (file == NULL || *file == '\0') + return; + + /* Initialise throwback. */ + if (!arm_throwback_started) + arm_throwback_start(); + + if (arm_throwback_started > 0 && riscos_canonicalise_filename (file)) + { + char message[256]; + + arm_throwback_new_file (arm_error_file); + /* We might have been passed a null argument pointer. */ + if (ap) + vsnprintf (message, 256, s, ap); + /* Traditionally, warning messages are prefixed by the + word 'warning'. */ + arm_throwback_error (arm_error_file, + (prefix && strcmp (prefix, "warning") == 0) + ? THROWBACK_WARNING : THROWBACK_ERROR, + line, (ap) ? message : s); + } +} + +/* Error category mapping for GNAT errors. */ +typedef enum +{ + cat_none, + cat_warning, + cat_error +} category; + +/* Throwback an error from GNAT. + The column parameter is unused, but maybe the throwback system will + be able to use it sometime in the future. */ +void +arm_gnat_error_throwback (text, sname, sfile, line, column, cat) + char *text; /* The error message. */ + char *sname; /* The file containing the error. */ + int sfile; /* A unique reference number for the file. */ + int line; /* The line number of the error. */ + int column; /* The column of the error. */ + category cat; /* The category of the error. */ +{ + /* If the filename is not specified or "", then return. */ + if (sname == NULL || *sname == '\0') + return; + /* Initialise throwback. */ + if (!arm_throwback_started) + arm_throwback_start(); + + if (arm_throwback_started > 0) + { + /* If this is a new file, then work out the RISC OS name and + canonicalise the name so that throwback knows the full pathname + of the file. */ + if (sfile != arm_error_file_ref) + { + arm_error_file_ref = sfile; + if (riscos_canonicalise_filename (sname)) + arm_throwback_new_file (arm_error_file); + else + arm_throwback_started = -1; + } + /* Promote category none into category error. */ + if (cat == cat_none) + cat = cat_error; + /* Throwback working, so send the message. */ + if (arm_throwback_started > 0) + arm_throwback_error (arm_error_file, + (cat == cat_none + ? THROWBACK_INFORMATION + : (cat == cat_warning + ? THROWBACK_WARNING : THROWBACK_ERROR)), + line, text); + } +} Index: gcc/config/arm/riscos.md =================================================================== RCS file: gcc/config/arm/riscos.md diff -N gcc/config/arm/riscos.md --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ gcc/config/arm/riscos.md 8 Feb 2005 01:20:34 -0000 1.1 @@ -0,0 +1,136 @@ +;; Implementations for dyamic allocation off the stack. + +;; These patterns say how to perform an equivalent to dynamic allocation +;; off the stack. We use library routines to return malloced memory +;; then alter the frame pointer so that on function exit, all chunks +;; will be freed. This system also works for different blocks within a +;; function. + +;; We do not need to worry about the outermost block in a function since +;; function exit will tidy up all unalloced chunks. + +(define_expand "save_stack_function" + [(use (const_int 0))] + "TARGET_APCS_STACK" + "") + +(define_expand "restore_stack_function" + [(use (const_int 0))] + "TARGET_APCS_STACK" + "") + +;; On entrance to a block, with __builtin_alloca, create a unique key +;; suitable for the free code. + +(define_expand "save_stack_block" + [(match_operand:SI 0 "memory_operand" "") + (match_operand:SI 1 "s_register_operand" "")] + "TARGET_APCS_STACK" + " +{ +#if 1 + /* Inline version of __arm_alloca_block_init. */ + rtx scratch_reg = gen_reg_rtx (SImode); + rtx label = gen_rtx_SYMBOL_REF (Pmode, \"__arm_alloca_st\"); + + emit_move_insn (scratch_reg, gen_rtx_MEM (SImode, label)); + emit_insn (gen_addsi3 (scratch_reg, scratch_reg, const1_rtx)); + emit_move_insn (gen_rtx_MEM (SImode, label), scratch_reg); +#else + rtx r0_rtx = gen_rtx (REG, SImode, 0); + rtx funexp = gen_rtx (SYMBOL_REF, Pmode, \"___arm_alloca_block_init\"); + + emit_call_insn (gen_call_value (r0_rtx, + gen_rtx (MEM, FUNCTION_MODE, funexp), + const0_rtx)); + emit_move_insn (operands[0], r0_rtx); +#endif + DONE; +}") + +(define_expand "save_stack_nonlocal" + [(match_operand:SI 0 "memory_operand" "") + (match_operand:SI 1 "s_register_operand" "")] + "TARGET_APCS_STACK" + " +{ +#if 1 + /* Inline version of __arm_alloca_block_init. */ + rtx scratch_reg = gen_reg_rtx (SImode); + rtx label = gen_rtx_SYMBOL_REF (Pmode, \"__arm_alloca_st\"); + + emit_move_insn (scratch_reg, gen_rtx_MEM (SImode, label)); + emit_insn (gen_addsi3 (scratch_reg, scratch_reg, const1_rtx)); + emit_move_insn (gen_rtx_MEM (SImode, label), scratch_reg); +#else + rtx r0_rtx = gen_rtx (REG, SImode, 0); + rtx funexp = gen_rtx (SYMBOL_REF, Pmode, \"___arm_alloca_block_init\"); + + emit_call_insn (gen_call_value (r0_rtx, + gen_rtx (MEM, FUNCTION_MODE, funexp), + const0_rtx)); + emit_move_insn (operands[0], r0_rtx); +#endif + DONE; +}") + + +;; Use the unique key produced earlier to free chunks created under +;; this key. + +(define_expand "restore_stack_block" + [(set (match_dup 2) (mem:SI (match_operand:SI 0 "s_register_operand" ""))) + (set (match_dup 0) (match_operand:SI 1 "s_register_operand" "")) + (set (mem:SI (match_dup 0)) (match_dup 2))] + "TARGET_APCS_STACK" + " +{ + rtx r0_rtx = gen_rtx (REG, SImode, 0); + rtx funexp = gen_rtx (SYMBOL_REF, Pmode, \"___arm_alloca_block_free\"); + + emit_move_insn (r0_rtx, operands[1]); + emit_insn (gen_rtx (USE, VOIDmode, r0_rtx)); + emit_call_insn (gen_call (gen_rtx (MEM, FUNCTION_MODE, funexp), GEN_INT (4))); + DONE; +}") + +(define_expand "restore_stack_nonlocal" + [(match_operand:SI 0 "s_register_operand" "") + (match_operand:SI 1 "memory_operand" "")] + "TARGET_APCS_STACK" + " +{ + rtx r0_rtx = gen_rtx (REG, SImode, 0); + rtx funexp = gen_rtx (SYMBOL_REF, Pmode, \"___arm_alloca_block_free\"); + + emit_move_insn (r0_rtx, operands[1]); + emit_insn (gen_rtx (USE, VOIDmode, r0_rtx)); + emit_call_insn (gen_call (gen_rtx (MEM, FUNCTION_MODE, funexp), GEN_INT (4))); + DONE; +}") + + +;; Call the function that will reserve the necessary amount of memory + +(define_expand "allocate_stack" + [(set (match_operand:SI 0 "s_register_operand" "=r") + (minus:SI (reg:SI 13) (match_operand:SI 1 "reg_or_int_operand" ""))) + (set (reg:SI 13) + (minus:SI (reg:SI 13) (match_dup 1))) + (clobber (reg:SI 0)) + (clobber (reg:SI 14))] + "TARGET_APCS_STACK" + " +{ + rtx r0_rtx = gen_rtx (REG, SImode, 0); + rtx funexp = gen_rtx (SYMBOL_REF, Pmode, \"___arm_alloca_alloc\"); + + emit_move_insn (r0_rtx, operands[1]); + emit_insn (gen_rtx (USE, VOIDmode, r0_rtx)); + emit_call_insn (gen_call_value (r0_rtx, + gen_rtx (MEM, FUNCTION_MODE, funexp), + GEN_INT (4))); + emit_move_insn (operands[0], r0_rtx); + + DONE; +}") Index: gcc/config/arm/xm-riscos.h =================================================================== RCS file: gcc/config/arm/xm-riscos.h diff -N gcc/config/arm/xm-riscos.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ gcc/config/arm/xm-riscos.h 8 Feb 2005 01:20:34 -0000 1.1 @@ -0,0 +1,60 @@ +/* Configuration for GNU compilers for processor running RISC OS. + Copyright (C) 1998 Free Software Foundation, Inc. + Contributed by Nick Burrett (nick.burrett@btinternet.com) + +This file is part of GNU CC. + +GNU CC 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. + +GNU CC 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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* This file defines all the specific features for GCC when running + on RISC OS. It is intended for compilation with UnixLib 3.7c. */ + +/* For the throwback of GCC errors to a text editor. */ +extern void arm_error_throwback (); +extern void arm_throwback_finish (); +extern void arm_gnat_error_throwback (); + +#if !defined (__GNUC__) && defined(__riscos) +/* For Acorn C to compile a stage 1 compiler, these must be defined. */ +#define CODE_FIELD_BUG 1 +#define ONLY_INT_FIELDS 1 +#endif + +#ifndef CROSS_COMPILE +/* Defines for the implementation of throwbacks. */ + +#define ERROR_THROWBACK(FILE,LINE,PREFIX,S,AP) \ +{ \ + if (TARGET_THROWBACK) \ + arm_error_throwback (FILE, LINE, PREFIX, S, AP); \ +} + +#define ERROR_THROWBACK_FINALISE arm_throwback_finish () +#endif + +/* Character constant used in separating components in paths. */ +#define PATH_SEPARATOR ',' + +/* Directory name separator. */ +#define DIR_SEPARATOR '/' + +/* We don't have STAB (or any) debugging info, at the moment. */ +#define NO_STAB_H + +/* Maths operation domain error number, EDOM. For CLib it is 1. */ +#define TARGET_EDOM 33 + +#include Index: gcc/cp/Makefile.riscpkg =================================================================== RCS file: gcc/cp/Makefile.riscpkg diff -N gcc/cp/Makefile.riscpkg --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ gcc/cp/Makefile.riscpkg 20 Feb 2005 20:22:10 -0000 1.2 @@ -0,0 +1,31 @@ +# This file is part of the RISC OS Packaging Project distribution of GCC. +# Copyright © 2005 Graham Shaw. +# Distribution and use are subject to the same terms as GCC as a whole. + +CXX_OBJS_CP = call.o decl.o errfn.o expr.o pt.o sig.o typeck2.o \ + class.o decl2.o error.o lex.o parse.o ptree.o rtti.o spew.o typeck.o cvt.o \ + except.o friend.o init.o method.o search.o semantics.o tree.o xref.o \ + repo.o + +GXX_OBJS_CP = g++.o g++spec.o +GXX_OBJS = prefix.o version.o + +CXX_OBJS_FULL = $(addprefix cp/,$(CXX_OBJS_CP)) +GXX_OBJS_FULL = $(addprefix cp/,$(GXX_OBJS_CP)) $(GXX_OBJS) + +xg++: $(GXX_OBJS_FULL) libgcc.a + $(LD) -o $@ $^ $(LIBS) + +cc1plus: $(CXX_OBJS_FULL) c-common.o $(OBJS) $(RISCOS_OBJS) libgcc.a + $(LD) -o $@ $^ $(LIBS) + +cp/g++.o: gcc.c + $(CC) -c $(CPPFLAGS) $(CCFLAGS) -o $@ $^ -DLANG_SPECIFIC_DRIVER + +$(CXX_OBJS_FULL): cp +$(GCC_OBJS_FULL): cp + +cp: always + mkdir -p cp + +.PHONY: always Index: libiberty/Makefile.riscpkg =================================================================== RCS file: libiberty/Makefile.riscpkg diff -N libiberty/Makefile.riscpkg --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ libiberty/Makefile.riscpkg 10 Feb 2005 02:36:29 -0000 1.1 @@ -0,0 +1,61 @@ +# This file is part of the RISC OS Packaging Project distribution of GCC. +# Copyright © 2005 Graham Shaw. +# Distribution and use are subject to the same terms as GCC as a whole. + +include fixdeps:Rules/make + +topdir=../.. +srcdir=.. + +ifeq (stage2,$(stage)) +CC = $(topdir)/gcc/stage1/xgcc -B$(topdir)/gcc/stage1/ +endif + +ifeq (stage3,$(stage)) +CC = $(topdir)/gcc/stage2/xgcc -B$(topdir)/gcc/stage2/ +endif + +CPPFLAGS = \ + -nostdinc \ + -I$(topdir)/include \ + -I/unixlib: \ + -I$(topdir)/gcc/ginclude \ + -I$(srcdir) + +vpath %.h $(srcdir) +vpath %.c $(srcdir) + +SRC = \ + argv.c \ + asprintf.c \ + choose-temp.c \ + concat.c \ + cplus-dem.c \ + fdmatch.c \ + floatformat.c \ + fnmatch.c \ + getopt.c \ + getopt1.c \ + getruntime.c \ + hex.c \ + insque.c \ + mkstemps.c \ + objalloc.c \ + obstack.c \ + pexecute.c \ + spaces.c \ + splay-tree.c \ + strerror.c \ + strsignal.c \ + vasprintf.c \ + xatexit.c \ + xexit.c \ + xmalloc.c \ + xstrdup.c \ + xstrerror.c + +libiberty.a: $(SRC:.c=.o) + mkdir -p a + $(AR) -c a.libiberty $(SRC:%.c=o.%) + +include $(SRC:.c=.d) Index: libiberty/config.h =================================================================== RCS file: libiberty/config.h diff -N libiberty/config.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ libiberty/config.h 9 Feb 2005 06:23:20 -0000 1.1 @@ -0,0 +1,222 @@ +/* config.h. Hand-edited from config.in by Graham Shaw to match + * features provided by GCC and UnixLib. */ + +/* Define if using alloca.c. */ +#undef C_ALLOCA + +/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. + This function is required for alloca.c support on those systems. */ +#undef CRAY_STACKSEG_END + +/* Define if you have alloca, as a function or macro. */ +#define HAVE_ALLOCA 1 + +/* Define if you have and it should be used (not on Ultrix). */ +#define HAVE_ALLOCA_H 1 + +/* Define if you have that is POSIX.1 compatible. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define if you have . */ +#undef HAVE_VFORK_H + +/* Define to `int' if doesn't define. */ +#undef pid_t + +/* Define if you need to in order for stat and other things to work. */ +#undef _POSIX_SOURCE + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown + */ +#undef STACK_DIRECTION + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define vfork as fork if vfork does not work. */ +#undef vfork + +/* Define if you have the sys_errlist variable. */ +#define HAVE_SYS_ERRLIST 1 + +/* Define if you have the sys_nerr variable. */ +#define HAVE_SYS_NERR 1 + +/* Define if you have the sys_siglist variable. */ +#define HAVE_SYS_SIGLIST 1 + +/* Define if you have the strerror function. */ +#define HAVE_STRERROR 1 + +/* Define if you have the asprintf function. */ +#undef HAVE_ASPRINTF + +/* Define if you have the atexit function. */ +#define HAVE_ATEXIT 1 + +/* Define if you have the basename function. */ +#undef HAVE_BASENAME + +/* Define if you have the bcmp function. */ +#define HAVE_BCMP 1 + +/* Define if you have the bcopy function. */ +#define HAVE_BCOPY 1 + +/* Define if you have the bzero function. */ +#define HAVE_BZERO 1 + +/* Define if you have the calloc function. */ +#define HAVE_CALLOC 1 + +/* Define if you have the clock function. */ +#define HAVE_CLOCK 1 + +/* Define if you have the getcwd function. */ +#define HAVE_GETCWD 1 + +/* Define if you have the getpagesize function. */ +#define HAVE_GETPAGESIZE 1 + +/* Define if you have the getrusage function. */ +#define HAVE_GETRUSAGE 1 + +/* Define if you have the gettimeofday function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define if you have the index function. */ +#define HAVE_INDEX 1 + +/* Define if you have the insque function. */ +#undef HAVE_INSQUE + +/* Define if you have the memchr function. */ +#define HAVE_MEMCHR 1 + +/* Define if you have the memcmp function. */ +#define HAVE_MEMCMP 1 + +/* Define if you have the memcpy function. */ +#define HAVE_MEMCPY 1 + +/* Define if you have the memmove function. */ +#define HAVE_MEMMOVE 1 + +/* Define if you have the memset function. */ +#define HAVE_MEMSET 1 + +/* Define if you have the mkstemps function. */ +#undef HAVE_MKSTEMPS + +/* Define if you have the on_exit function. */ +#undef HAVE_ON_EXIT + +/* Define if you have the psignal function. */ +#define HAVE_PSIGNAL 1 + +/* Define if you have the putenv function. */ +#define HAVE_PUTENV 1 + +/* Define if you have the random function. */ +#define HAVE_RANDOM 1 + +/* Define if you have the rename function. */ +#define HAVE_RENAME 1 + +/* Define if you have the rindex function. */ +#define HAVE_RINDEX 1 + +/* Define if you have the sbrk function. */ +#define HAVE_SBRK 1 + +/* Define if you have the setenv function. */ +#define HAVE_SETENV 1 + +/* Define if you have the sigsetmask function. */ +#define HAVE_SIGSETMASK 1 + +/* Define if you have the strcasecmp function. */ +#define HAVE_STRCASECMP 1 + +/* Define if you have the strchr function. */ +#define HAVE_STRCHR 1 + +/* Define if you have the strdup function. */ +#define HAVE_STRDUP 1 + +/* Define if you have the strerror function. */ +#define HAVE_STRERROR 1 + +/* Define if you have the strncasecmp function. */ +#define HAVE_STRNCASECMP 1 + +/* Define if you have the strrchr function. */ +#define HAVE_STRRCHR 1 + +/* Define if you have the strsignal function. */ +#define HAVE_STRSIGNAL 1 + +/* Define if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define if you have the strtod function. */ +#define HAVE_STRTOD 1 + +/* Define if you have the strtol function. */ +#define HAVE_STRTOL 1 + +/* Define if you have the strtoul function. */ +#define HAVE_STRTOUL 1 + +/* Define if you have the sysconf function. */ +#define HAVE_SYSCONF 1 + +/* Define if you have the times function. */ +#define HAVE_TIMES 1 + +/* Define if you have the tmpnam function. */ +#define HAVE_TMPNAM 1 + +/* Define if you have the vasprintf function. */ +#undef HAVE_VASPRINTF + +/* Define if you have the vfprintf function. */ +#define HAVE_VFPRINTF 1 + +/* Define if you have the vprintf function. */ +#define HAVE_VPRINTF 1 + +/* Define if you have the vsprintf function. */ +#define HAVE_VSPRINTF 1 + +/* Define if you have the waitpid function. */ +#define HAVE_WAITPID 1 + +/* Define if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_FILE_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define if you have the header file. */ +#define HAVE_UNISTD_H 1 Index: libio/Makefile.riscpkg =================================================================== RCS file: libio/Makefile.riscpkg diff -N libio/Makefile.riscpkg --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ libio/Makefile.riscpkg 15 Feb 2005 14:34:29 -0000 1.1 @@ -0,0 +1,72 @@ +# This file is part of the RISC OS Packaging Project distribution of GCC. +# Copyright © 2005 Graham Shaw. +# Distribution and use are subject to the same terms as GCC as a whole. + +include fixdeps:Rules/make + +topdir=../.. +srcdir=.. + +ifeq (stage2,$(stage)) +CC = $(topdir)/gcc/stage2/xgcc -B$(topdir)/gcc/stage2/ +CXX = $(topdir)/gcc/stage2/xgcc -B$(topdir)/gcc/stage2/ +endif + +ifeq (stage3,$(stage)) +CC = $(topdir)/gcc/stage3/xgcc -B$(topdir)/gcc/stage3/ +CXX = $(topdir)/gcc/stage3/xgcc -B$(topdir)/gcc/stage3/ +endif + +CPPFLAGS = \ + -nostdinc \ + -I$(srcdir) \ + -I$(topdir)/include \ + -I$(topdir)/gcc/ginclude \ + -I$(topdir)/gcc/cp/inc \ + -I/unixlib: + +CCFLAGS = -mthrowback -munixlib -mpoke-function-name -O2 +CXXFLAGS = -mthrowback -munixlib -mpoke-function-name -O2 + +vpath %.h $(srcdir) +vpath %.c $(srcdir) +vpath %.cc $(srcdir) + +IO_OBJECTS = filedoalloc.o floatconv.o genops.o fileops.o iovfprintf.o \ + iovfscanf.o ioignore.o iopadn.o iofgetpos.o iofread.o iofscanf.o \ + iofsetpos.o iogetdelim.o iogetline.o ioprintf.o ioseekoff.o \ + ioseekpos.o outfloat.o strops.o iofclose.o iopopen.o ioungetc.o peekc.o \ + iogetc.o ioputc.o iofeof.o ioferror.o + +STDIO_OBJECTS = stdfiles.o + +STDIO_WRAP_OBJECTS = iofdopen.o iofflush.o iofgets.o iofopen.o \ + iofprintf.o iofputs.o iofwrite.o iogets.o ioperror.o ioputs.o ioscanf.o \ + iosetbuffer.o iosetvbuf.o iosprintf.o iosscanf.o ioftell.o iovsprintf.o \ + iovsscanf.o + +IOSTREAM_OBJECTS = builtinbuf.o filebuf.o fstream.o indstream.o \ + ioassign.o ioextend.o iomanip.o iostream.o isgetline.o isgetsb.o \ + isscan.o osform.o procbuf.o sbform.o sbgetline.o sbscan.o \ + stdiostream.o stdstrbufs.o stdstreams.o stream.o streambuf.o \ + strstream.o PlotFile.o SFile.o parsestream.o pfstream.o editbuf.o + +OSPRIM_OBJECTS = ioprims.o iostrerror.o cleanup.o + +LIBIOSTREAM_OBJECTS = $(IO_OBJECTS) $(IOSTREAM_OBJECTS) $(OSPRIM_OBJECTS) +LIBIO_OBJECTS = $(IO_OBJECTS) $(STDIO_WRAP_OBJECTS) $(OSPRIM_OBJECTS) \ + $(STDIO_OBJECTS) + +.PHONY: all +all: libio.a libiostream.a + +libio.a: $(LIBIO_OBJECTS) + mkdir -p a + $(AR) -c a.libio $(LIBIO_OBJECTS:%.o=o.%) + +libiostream.a: $(LIBIOSTREAM_OBJECTS) + mkdir -p a + $(AR) -c a.libiostream $(LIBIOSTREAM_OBJECTS:%.o=o.%) + +# include $(IO_OBJECTS:.o=.d) +# and the others too ... \ No newline at end of file Index: libio/_G_config.h =================================================================== RCS file: libio/_G_config.h diff -N libio/_G_config.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ libio/_G_config.h 15 Feb 2005 14:34:29 -0000 1.1 @@ -0,0 +1,135 @@ +/* This file is generated by hand since the shell scripts won't run + on my Acorn. + I hope that someday something more automatic can be created. + */ +#ifndef _G_config_h +#define _G_config_h +#include + +#define _G_LIB_VERSION "2.8.0" +/* Our version of GCC does not prepend an underscore to names. */ +#define _G_NAMES_HAVE_UNDERSCORE 0 +/* No dollars in labels please. */ +/* #define _G_DOLLAR_IN_LABEL 0 */ +/* Define how virtual function tables are named. */ +#define _G_VTABLE_LABEL_PREFIX "_vt$" +/* If _G_VTABLE_LABEL_PREFIX = __vt_ or ___vt_ + then we define _G_USING_THUNKS. */ +/* #define _G_USING_THUNKS */ +#define _G_VTABLE_LABEL_HAS_LENGTH 1 +/* VTABLE_LABEL_PREFIX_ID is the same as VTABLE_LABEL_PREFIX but + the former is a C identifier, while the latter is a quoted + string. */ +#define _G_VTABLE_LABEL_PREFIX_ID _vt$ +/* The struct stat has st_blksize. */ +#define _G_HAVE_ST_BLKSIZE 1 +#define _G_CLOG_CONFLICT 1 + +/* Definitions for the standard types (such as mode_t). */ + +typedef unsigned int _G_sigset_t; + +typedef int _G_pid_t; +typedef unsigned int _G_gid_t; +typedef unsigned int _G_uid_t; +typedef unsigned int _G_mode_t; +typedef unsigned int _G_clock_t; +typedef int _G_dev_t; +typedef long int _G_fpos_t; +typedef long int _G_off_t; +typedef unsigned short int _G_nlink_t; +typedef unsigned int _G_ino_t; +#ifndef __PTRDIFF_TYPE__ +#define __PTRDIFF_TYPE__ int +#endif +typedef __PTRDIFF_TYPE__ _G_ptrdiff_t; +#ifndef __SIZE_TYPE__ +#define __SIZE_TYPE__ unsigned int +#endif +typedef __SIZE_TYPE__ _G_size_t; +typedef unsigned int _G_time_t; +typedef int _G_ssize_t; +#ifndef __WCHAR_TYPE__ +#define __WCHAR_TYPE__ unsigned int +#endif +typedef unsigned int _G_wchar_t; +typedef unsigned int _G_wint_t; +typedef char * _G_va_list; + +#define _G_signal_return_type int +#define _G_sprintf_return_type int + +/* Taken from for UnixLib 3.7a. */ +#define _G_SHRT_MAX SHRT_MAX +#define _G_INT_MAX INT_MAX +#define _G_LONG_MAX LONG_MAX +#define _G_LONG_LONG_MAX LONG_LONG_MAX + +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) +typedef int _G_int8_t __attribute__ ((__mode__ (__QI__))); +typedef unsigned int _G_uint8_t __attribute__ ((__mode__ (__QI__))); +typedef int _G_int16_t __attribute__ ((__mode__ (__HI__))); +typedef unsigned int _G_uint16_t __attribute__ ((__mode__ (__HI__))); +typedef int _G_int32_t __attribute__ ((__mode__ (__SI__))); +typedef unsigned int _G_uint32_t __attribute__ ((__mode__ (__SI__))); +typedef int _G_int64_t __attribute__ ((__mode__ (__DI__))); +typedef unsigned int _G_uint64_t __attribute__ ((__mode__ (__DI__))); +#if __GNUC__ > 2 || __GNUC_MINOR__ >= 8 +__extension__ typedef long long _G_llong; +__extension__ typedef unsigned long long _G_ullong; +#endif +#else +typedef short _G_int16_t; +typedef unsigned short _G_uint16_t; +typedef int _G_int32_t; +typedef unsigned int _G_uint32_t; +#endif + +#define _G_BUFSIZ 4096 +#define _G_FOPEN_MAX 64 +#define _G_FILENAME_MAX 252 +#define _G_NULL 0 + +#if defined (__cplusplus) || defined (__STDC__) +#define _G_ARGS(ARGLIST) ARGLIST +#else +#define _G_ARGS(ARGLIST) () +#endif +#if !defined (__GNUG__) || defined (__STRICT_ANSI__) +#define _G_NO_NRV +#endif +#if !defined (__GNUG__) +#define _G_NO_EXTERN_TEMPLATES +#endif + +#define _G_NEED_STDARG_H 1 + +/* We have the atexit function. */ +#define _G_HAVE_ATEXIT 1 +/* We do not have the sys/resource.h file. */ +#define _G_HAVE_SYS_RESOURCE 1 +/* We have sys/times.h and the structure tms. */ +#define _G_HAVE_SYS_TIMES 1 +/* We do not have sys/socket.h. */ +#define _G_HAVE_SYS_SOCKET 0 +/* We have sys/cdefs.h. */ +#define _G_HAVE_SYS_CDEFS 1 +/* We have sys/wait.h and it is POSIX compatible. */ +#ifndef __TARGET_SCL__ +#define _G_HAVE_SYS_WAIT 1 +#endif +/* Got a unistd.h. */ +#define _G_HAVE_UNISTD 1 +/* Got a dirent.h. */ +#define _G_HAVE_DIRENT 1 +/* We don't have curses.h. */ +#define _G_HAVE_CURSES 0 +/* math.h does not inline anything. */ +#define _G_MATH_H_INLINES 0 +/* We have the define BOOL defined. */ +#define _G_HAVE_BOOL 1 +#define _G_HAVE_PRINTF_FP 0 +#define _G_HAVE_LONG_DOUBLE_IO 0 +/* Uncommend the following line if you don't have working templates. */ +/* #define _G_NO_TEMPLATES */ +#endif /* !_G_config_h */ Index: libstdc++/Makefile.riscpkg =================================================================== RCS file: libstdc++/Makefile.riscpkg diff -N libstdc++/Makefile.riscpkg --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ libstdc++/Makefile.riscpkg 15 Feb 2005 14:34:29 -0000 1.1 @@ -0,0 +1,81 @@ +# This file is part of the RISC OS Packaging Project distribution of GCC. +# Copyright © 2005 Graham Shaw. +# Distribution and use are subject to the same terms as GCC as a whole. + +include fixdeps:Rules/make + +topdir=../.. +srcdir=.. + +ifeq (stage2,$(stage)) +CC = $(topdir)/gcc/stage2/xgcc -B$(topdir)/gcc/stage2/ +CXX = $(topdir)/gcc/stage2/xgcc -B$(topdir)/gcc/stage2/ +endif + +ifeq (stage3,$(stage)) +CC = $(topdir)/gcc/stage3/xgcc -B$(topdir)/gcc/stage3/ +CXX = $(topdir)/gcc/stage3/xgcc -B$(topdir)/gcc/stage3/ +endif + +CPPFLAGS = \ + -nostdinc \ + -I- \ + -I$(srcdir) \ + -I$(topdir)/libio \ + -I$(srcdir)/stl \ + -I$(topdir)/include \ + -I$(topdir)/gcc/ginclude \ + -I$(topdir)/gcc/cp/inc \ + -I/unixlib: \ + +CCFLAGS = -mthrowback -munixlib -mpoke-function-name -O2 +CXXFLAGS = -mthrowback -munixlib -mpoke-function-name -O2 + +vpath %.h $(srcdir) +vpath %.cc $(srcdir) + +STR_FUNCS = REP MAIN TRAITS ADDSS ADDPS ADDCS ADDSP ADDSC \ + EQSS EQPS EQSP NESS NEPS NESP LTSS LTPS LTSP GTSS GTPS GTSP \ + LESS LEPS LESP GESS GEPS GESP + +STR_IO = EXTRACT INSERT GETLINE + +COM_FUNCS = MAIN ADDCC ADDCF ADDFC SUBCC SUBCF SUBFC MULCC MULCF MULFC DIVCC \ + DIVCF DIVFC PLUS MINUS EQCC EQCF EQFC NECC NECF NEFC ABS ARG POLAR \ + CONJ NORM COS COSH EXP LOG POWCC POWCF POWCI POWFC SIN SINH SQRT + +COM_IO = EXTRACT INSERT + +OBJS = cstringi.o stdexcepti.o cstdlibi.o cmathi.o stlinst.o valarray.o + +STR_XOBJS = $(addsuffix .o,$(STR_FUNCS) $(STR_IO)) +STR_OBJS = $(addprefix C,$(STR_XOBJS)) + +COM_XOBJS = $(addsuffix .o,$(COM_FUNCS) $(COM_IO)) +COM_FOBJS = $(addprefix F,$(COM_XOBJS)) +COM_DOBJS = $(addprefix D,$(COM_XOBJS)) +COM_LDOBJS = $(addprefix LD,$(COM_XOBJS)) + +ALL_OBJS = $(OBJS) $(STR_OBJS) $(COM_FOBJS) $(COM_DOBJS) $(COM_LDOBJS) + +.PHONY: all +all: libstdc++.a + +libstdc++.a: $(ALL_OBJS) + mkdir -p a + $(AR) -c a.libstdc++ $(ALL_OBJS:%.o=o.%) + +$(STR_OBJS): C%.o: sinst.cc + $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) -o $@ $^ -DC -D$* + +$(COM_FOBJS): F%.o: cinst.cc + $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) -o $@ $^ -DF -D$* + +$(COM_DOBJS): D%.o: cinst.cc + $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) -o $@ $^ -DD -D$* + +$(COM_LDOBJS): LD%.o: cinst.cc + $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) -o $@ $^ -DLD -D$* + +include sinst.d +include cinst.d