summaryrefslogtreecommitdiff
path: root/gcc/config/arm
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/arm')
-rwxr-xr-xgcc/config/arm/README-interworking742
-rwxr-xr-xgcc/config/arm/lib1thumb.asm736
-rwxr-xr-xgcc/config/arm/t-thumb-elf32
-rwxr-xr-xgcc/config/arm/telf.h368
-rwxr-xr-xgcc/config/arm/thumb.c1527
-rwxr-xr-xgcc/config/arm/thumb.h1137
-rwxr-xr-xgcc/config/arm/thumb.md1157
7 files changed, 0 insertions, 5699 deletions
diff --git a/gcc/config/arm/README-interworking b/gcc/config/arm/README-interworking
deleted file mode 100755
index 46b76c9..0000000
--- a/gcc/config/arm/README-interworking
+++ /dev/null
@@ -1,742 +0,0 @@
- Arm / Thumb Interworking
- ========================
-
-The Cygnus GNU Pro Toolkit for the ARM7T processor supports function
-calls between code compiled for the ARM instruction set and code
-compiled for the Thumb instruction set and vice versa. This document
-describes how that interworking support operates and explains the
-command line switches that should be used in order to produce working
-programs.
-
-Note: The Cygnus GNU Pro Toolkit does not support switching between
-compiling for the ARM instruction set and the Thumb instruction set
-on anything other than a per file basis. There are in fact two
-completely separate compilers, one that produces ARM assembler
-instructions and one that produces Thumb assembler instructions. The
-two compilers share the same assembler, linker and so on.
-
-
-1. Explicit interworking support for C and C++ files
-====================================================
-
-By default if a file is compiled without any special command line
-switches then the code produced will not support interworking.
-Provided that a program is made up entirely from object files and
-libraries produced in this way and which contain either exclusively
-ARM instructions or exclusively Thumb instructions then this will not
-matter and a working executable will be created. If an attempt is
-made to link together mixed ARM and Thumb object files and libraries,
-then warning messages will be produced by the linker and a non-working
-executable will be created.
-
-In order to produce code which does support interworking it should be
-compiled with the
-
- -mthumb-interwork
-
-command line option. Provided that a program is made up entirely from
-object files and libraries built with this command line switch a
-working executable will be produced, even if both ARM and Thumb
-instructions are used by the various components of the program. (No
-warning messages will be produced by the linker either).
-
-Note that specifying -mthumb-interwork does result in slightly larger,
-slower code being produced. This is why interworking support must be
-specifically enabled by a switch.
-
-
-2. Explicit interworking support for assembler files
-====================================================
-
-If assembler files are to be included into an interworking program
-then the following rules must be obeyed:
-
- * Any externally visible functions must return by using the BX
- instruction.
-
- * Normal function calls can just use the BL instruction. The
- linker will automatically insert code to switch between ARM
- and Thumb modes as necessary.
-
- * Calls via function pointers should use the BX instruction if
- the call is made in ARM mode:
-
- .code 32
- mov lr, pc
- bx rX
-
- This code sequence will not work in Thumb mode however, since
- the mov instruction will not set the bottom bit of the lr
- register. Instead a branch-and-link to the _call_via_rX
- functions should be used instead:
-
- .code 16
- bl _call_via_rX
-
- where rX is replaced by the name of the register containing
- the function address.
-
- * All externally visible functions which should be entered in
- Thumb mode must have the .thumb_func pseudo op specified just
- before their entry point. eg:
-
- .code 16
- .global function
- .thumb_func
- function:
- ...start of function....
-
- * All assembler files must be assembled with the switch
- -mthumb-interwork specified on the command line. (If the file
- is assembled by calling gcc it will automatically pass on the
- -mthumb-interwork switch to the assembler, provided that it
- was specified on the gcc command line in the first place.)
-
-
-3. Support for old, non-interworking aware code.
-================================================
-
-If it is necessary to link together code produced by an older,
-non-interworking aware compiler, or code produced by the new compiler
-but without the -mthumb-interwork command line switch specified, then
-there are two command line switches that can be used to support this.
-
-The switch
-
- -mcaller-super-interworking
-
-will allow calls via function pointers in Thumb mode to work,
-regardless of whether the function pointer points to old,
-non-interworking aware code or not. Specifying this switch does
-produce slightly slower code however.
-
-Note: There is no switch to allow calls via function pointers in ARM
-mode to be handled specially. Calls via function pointers from
-interworking aware ARM code to non-interworking aware ARM code work
-without any special considerations by the compiler. Calls via
-function pointers from interworking aware ARM code to non-interworking
-aware Thumb code however will not work. (Actually under some
-circumstances they may work, but there are no guarantees). This is
-because only the new compiler is able to produce Thumb code, and this
-compiler already has a command line switch to produce interworking
-aware code.
-
-
-The switch
-
- -mcallee-super-interworking
-
-will allow non-interworking aware ARM or Thumb code to call Thumb
-functions, either directly or via function pointers. Specifying this
-switch does produce slightly larger, slower code however.
-
-Note: There is no switch to allow non-interworking aware ARM or Thumb
-code to call ARM functions. There is no need for any special handling
-of calls from non-interworking aware ARM code to interworking aware
-ARM functions, they just work normally. Calls from non-interworking
-aware Thumb functions to ARM code however, will not work. There is no
-option to support this, since it is always possible to recompile the
-Thumb code to be interworking aware.
-
-As an alternative to the command line switch
--mcallee-super-interworking, which affects all externally visible
-functions in a file, it is possible to specify an attribute or
-declspec for individual functions, indicating that that particular
-function should support being called by non-interworking aware code.
-The function should be defined like this:
-
- int __attribute__((interfacearm)) function
- {
- ... body of function ...
- }
-
-or
-
- int __declspec(interfacearm) function
- {
- ... body of function ...
- }
-
-
-
-4. Interworking support in dlltool
-==================================
-
-It is possible to create DLLs containing mixed ARM and Thumb code. It
-is also possible to call Thumb code in a DLL from an ARM program and
-vice versa. It is even possible to call ARM DLLs that have been compiled
-without interworking support (say by an older version of the compiler),
-from Thumb programs and still have things work properly.
-
- A version of the `dlltool' program which supports the `--interwork'
-command line switch is needed, as well as the following special
-considerations when building programs and DLLs:
-
-*Use `-mthumb-interwork'*
- When compiling files for a DLL or a program the `-mthumb-interwork'
- command line switch should be specified if calling between ARM and
- Thumb code can happen. If a program is being compiled and the
- mode of the DLLs that it uses is not known, then it should be
- assumed that interworking might occur and the switch used.
-
-*Use `-m thumb'*
- If the exported functions from a DLL are all Thumb encoded then the
- `-m thumb' command line switch should be given to dlltool when
- building the stubs. This will make dlltool create Thumb encoded
- stubs, rather than its default of ARM encoded stubs.
-
- If the DLL consists of both exported Thumb functions and exported
- ARM functions then the `-m thumb' switch should not be used.
- Instead the Thumb functions in the DLL should be compiled with the
- `-mcallee-super-interworking' switch, or with the `interfacearm'
- attribute specified on their prototypes. In this way they will be
- given ARM encoded prologues, which will work with the ARM encoded
- stubs produced by dlltool.
-
-*Use `-mcaller-super-interworking'*
- If it is possible for Thumb functions in a DLL to call
- non-interworking aware code via a function pointer, then the Thumb
- code must be compiled with the `-mcaller-super-interworking'
- command line switch. This will force the function pointer calls
- to use the _interwork_call_via_rX stub functions which will
- correctly restore Thumb mode upon return from the called function.
-
-*Link with `libgcc.a'*
- When the dll is built it may have to be linked with the GCC
- library (`libgcc.a') in order to extract the _call_via_rX functions
- or the _interwork_call_via_rX functions. This represents a partial
- redundancy since the same functions *may* be present in the
- application itself, but since they only take up 372 bytes this
- should not be too much of a consideration.
-
-*Use `--support-old-code'*
- When linking a program with an old DLL which does not support
- interworking, the `--support-old-code' command line switch to the
- linker should be used. This causes the linker to generate special
- interworking stubs which can cope with old, non-interworking aware
- ARM code, at the cost of generating bulkier code. The linker will
- still generate a warning message along the lines of:
- "Warning: input file XXX does not support interworking, whereas YYY does."
- but this can now be ignored because the --support-old-code switch
- has been used.
-
-
-
-5. How interworking support works
-=================================
-
-Switching between the ARM and Thumb instruction sets is accomplished
-via the BX instruction which takes as an argument a register name.
-Control is transfered to the address held in this register (with the
-bottom bit masked out), and if the bottom bit is set, then Thumb
-instruction processing is enabled, otherwise ARM instruction
-processing is enabled.
-
-When the -mthumb-interwork command line switch is specified, gcc
-arranges for all functions to return to their caller by using the BX
-instruction. Thus provided that the return address has the bottom bit
-correctly initialised to indicate the instruction set of the caller,
-correct operation will ensue.
-
-When a function is called explicitly (rather than via a function
-pointer), the compiler generates a BL instruction to do this. The
-Thumb version of the BL instruction has the special property of
-setting the bottom bit of the LR register after it has stored the
-return address into it, so that a future BX instruction will correctly
-return the instruction after the BL instruction, in Thumb mode.
-
-The BL instruction does not change modes itself however, so if an ARM
-function is calling a Thumb function, or vice versa, it is necessary
-to generate some extra instructions to handle this. This is done in
-the linker when it is storing the address of the referenced function
-into the BL instruction. If the BL instruction is an ARM style BL
-instruction, but the referenced function is a Thumb function, then the
-linker automatically generates a calling stub that converts from ARM
-mode to Thumb mode, puts the address of this stub into the BL
-instruction, and puts the address of the referenced function into the
-stub. Similarly if the BL instruction is a Thumb BL instruction, and
-the referenced function is an ARM function, the linker generates a
-stub which converts from Thumb to ARM mode, puts the address of this
-stub into the BL instruction, and the address of the referenced
-function into the stub.
-
-This is why it is necessary to mark Thumb functions with the
-.thumb_func pseudo op when creating assembler files. This pseudo op
-allows the assembler to distinguish between ARM functions and Thumb
-functions. (The Thumb version of GCC automatically generates these
-pseudo ops for any Thumb functions that it generates).
-
-Calls via function pointers work differently. Whenever the address of
-a function is taken, the linker examines the type of the function
-being referenced. If the function is a Thumb function, then it sets
-the bottom bit of the address. Technically this makes the address
-incorrect, since it is now one byte into the start of the function,
-but this is never a problem because:
-
- a. with interworking enabled all calls via function pointer
- are done using the BX instruction and this ignores the
- bottom bit when computing where to go to.
-
- b. the linker will always set the bottom bit when the address
- of the function is taken, so it is never possible to take
- the address of the function in two different places and
- then compare them and find that they are not equal.
-
-As already mentioned any call via a function pointer will use the BX
-instruction (provided that interworking is enabled). The only problem
-with this is computing the return address for the return from the
-called function. For ARM code this can easily be done by the code
-sequence:
-
- mov lr, pc
- bx rX
-
-(where rX is the name of the register containing the function
-pointer). This code does not work for the Thumb instruction set,
-since the MOV instruction will not set the bottom bit of the LR
-register, so that when the called function returns, it will return in
-ARM mode not Thumb mode. Instead the compiler generates this
-sequence:
-
- bl _call_via_rX
-
-(again where rX is the name if the register containing the function
-pointer). The special call_via_rX functions look like this:
-
- .thumb_func
-_call_via_r0:
- bx r0
- nop
-
-The BL instruction ensures that the correct return address is stored
-in the LR register and then the BX instruction jumps to the address
-stored in the function pointer, switch modes if necessary.
-
-
-6. How caller-super-interworking support works
-==============================================
-
-When the -mcaller-super-interworking command line switch is specified
-it changes the code produced by the Thumb compiler so that all calls
-via function pointers (including virtual function calls) now go via a
-different stub function. The code to call via a function pointer now
-looks like this:
-
- bl _interwork_call_via_r0
-
-Note: The compiler does not insist that r0 be used to hold the
-function address. Any register will do, and there are a suite of stub
-functions, one for each possible register. The stub functions look
-like this:
-
- .code 16
- .thumb_func
-_interwork_call_via_r0
- bx pc
- nop
-
- .code 32
- tst r0, #1
- stmeqdb r13!, {lr}
- adreq lr, _arm_return
- bx r0
-
-The stub first switches to ARM mode, since it is a lot easier to
-perform the necessary operations using ARM instructions. It then
-tests the bottom bit of the register containing the address of the
-function to be called. If this bottom bit is set then the function
-being called uses Thumb instructions and the BX instruction to come
-will switch back into Thumb mode before calling this function. (Note
-that it does not matter how this called function chooses to return to
-its caller, since the both the caller and callee are Thumb functions,
-and mode switching is necessary). If the function being called is an
-ARM mode function however, the stub pushes the return address (with
-its bottom bit set) onto the stack, replaces the return address with
-the address of the a piece of code called '_arm_return' and then
-performs a BX instruction to call the function.
-
-The '_arm_return' code looks like this:
-
- .code 32
-_arm_return:
- ldmia r13!, {r12}
- bx r12
- .code 16
-
-
-It simply retrieves the return address from the stack, and then
-performs a BX operation to return to the caller and switch back into
-Thumb mode.
-
-
-7. How callee-super-interworking support works
-==============================================
-
-When -mcallee-super-interworking is specified on the command line the
-Thumb compiler behaves as if every externally visible function that it
-compiles has had the (interfacearm) attribute specified for it. What
-this attribute does is to put a special, ARM mode header onto the
-function which forces a switch into Thumb mode:
-
- without __attribute__((interfacearm)):
-
- .code 16
- .thumb_func
- function:
- ... start of function ...
-
- with __attribute__((interfacearm)):
-
- .code 32
- function:
- orr r12, pc, #1
- bx r12
-
- .code 16
- .thumb_func
- .real_start_of_function:
-
- ... start of function ...
-
-Note that since the function now expects to be entered in ARM mode, it
-no longer has the .thumb_func pseudo op specified for its name.
-Instead the pseudo op is attached to a new label .real_start_of_<name>
-(where <name> is the name of the function) which indicates the start
-of the Thumb code. This does have the interesting side effect in that
-if this function is now called from a Thumb mode piece of code
-outsside of the current file, the linker will generate a calling stub
-to switch from Thumb mode into ARM mode, and then this is immediately
-overridden by the function's header which switches back into Thumb
-mode.
-
-In addition the (interfacearm) attribute also forces the function to
-return by using the BX instruction, even if has not been compiled with
-the -mthumb-interwork command line flag, so that the correct mode will
-be restored upon exit from the function.
-
-
-8. Some examples
-================
-
- Given these two test files:
-
- int arm (void) { return 1 + thumb (); }
-
- int thumb (void) { return 2 + arm (); }
-
- The following pieces of assembler are produced by the ARM and Thumb
-version of GCC depending upon the command line options used:
-
- `-O2':
- .code 32 .code 16
- .global _arm .global _thumb
- .thumb_func
- _arm: _thumb:
- mov ip, sp
- stmfd sp!, {fp, ip, lr, pc} push {lr}
- sub fp, ip, #4
- bl _thumb bl _arm
- add r0, r0, #1 add r0, r0, #2
- ldmea fp, {fp, sp, pc} pop {pc}
-
- Note how the functions return without using the BX instruction. If
-these files were assembled and linked together they would fail to work
-because they do not change mode when returning to their caller.
-
- `-O2 -mthumb-interwork':
-
- .code 32 .code 16
- .global _arm .global _thumb
- .thumb_func
- _arm: _thumb:
- mov ip, sp
- stmfd sp!, {fp, ip, lr, pc} push {lr}
- sub fp, ip, #4
- bl _thumb bl _arm
- add r0, r0, #1 add r0, r0, #2
- ldmea fp, {fp, sp, lr} pop {r1}
- bx lr bx r1
-
- Now the functions use BX to return their caller. They have grown by
-4 and 2 bytes respectively, but they can now successfully be linked
-together and be expect to work. The linker will replace the
-destinations of the two BL instructions with the addresses of calling
-stubs which convert to the correct mode before jumping to the called
-function.
-
- `-O2 -mcallee-super-interworking':
-
- .code 32 .code 32
- .global _arm .global _thumb
- _arm: _thumb:
- orr r12, pc, #1
- bx r12
- mov ip, sp .code 16
- stmfd sp!, {fp, ip, lr, pc} push {lr}
- sub fp, ip, #4
- bl _thumb bl _arm
- add r0, r0, #1 add r0, r0, #2
- ldmea fp, {fp, sp, lr} pop {r1}
- bx lr bx r1
-
- The thumb function now has an ARM encoded prologue, and it no longer
-has the `.thumb-func' pseudo op attached to it. The linker will not
-generate a calling stub for the call from arm() to thumb(), but it will
-still have to generate a stub for the call from thumb() to arm(). Also
-note how specifying `--mcallee-super-interworking' automatically
-implies `-mthumb-interworking'.
-
-
-9. Some Function Pointer Examples
-=================================
-
- Given this test file:
-
- int func (void) { return 1; }
-
- int call (int (* ptr)(void)) { return ptr (); }
-
- The following varying pieces of assembler are produced by the Thumb
-version of GCC depending upon the command line options used:
-
- `-O2':
- .code 16
- .globl _func
- .thumb_func
- _func:
- mov r0, #1
- bx lr
-
- .globl _call
- .thumb_func
- _call:
- push {lr}
- bl __call_via_r0
- pop {pc}
-
- Note how the two functions have different exit sequences. In
-particular call() uses pop {pc} to return, which would not work if the
-caller was in ARM mode. func() however, uses the BX instruction, even
-though `-mthumb-interwork' has not been specified, as this is the most
-efficient way to exit a function when the return address is held in the
-link register.
-
- `-O2 -mthumb-interwork':
-
- .code 16
- .globl _func
- .thumb_func
- _func:
- mov r0, #1
- bx lr
-
- .globl _call
- .thumb_func
- _call:
- push {lr}
- bl __call_via_r0
- pop {r1}
- bx r1
-
- This time both functions return by using the BX instruction. This
-means that call() is now two bytes longer and several cycles slower
-than the previous version.
-
- `-O2 -mcaller-super-interworking':
- .code 16
- .globl _func
- .thumb_func
- _func:
- mov r0, #1
- bx lr
-
- .globl _call
- .thumb_func
- _call:
- push {lr}
- bl __interwork_call_via_r0
- pop {pc}
-
- Very similar to the first (non-interworking) version, except that a
-different stub is used to call via the function pointer. This new stub
-will work even if the called function is not interworking aware, and
-tries to return to call() in ARM mode. Note that the assembly code for
-call() is still not interworking aware itself, and so should not be
-called from ARM code.
-
- `-O2 -mcallee-super-interworking':
-
- .code 32
- .globl _func
- _func:
- orr r12, pc, #1
- bx r12
-
- .code 16
- .globl .real_start_of_func
- .thumb_func
- .real_start_of_func:
- mov r0, #1
- bx lr
-
- .code 32
- .globl _call
- _call:
- orr r12, pc, #1
- bx r12
-
- .code 16
- .globl .real_start_of_call
- .thumb_func
- .real_start_of_call:
- push {lr}
- bl __call_via_r0
- pop {r1}
- bx r1
-
- Now both functions have an ARM coded prologue, and both functions
-return by using the BX instruction. These functions are interworking
-aware therefore and can safely be called from ARM code. The code for
-the call() function is now 10 bytes longer than the original, non
-interworking aware version, an increase of over 200%.
-
- If a prototype for call() is added to the source code, and this
-prototype includes the `interfacearm' attribute:
-
- int __attribute__((interfacearm)) call (int (* ptr)(void));
-
- then this code is produced (with only -O2 specified on the command
-line):
-
- .code 16
- .globl _func
- .thumb_func
- _func:
- mov r0, #1
- bx lr
-
- .globl _call
- .code 32
- _call:
- orr r12, pc, #1
- bx r12
-
- .code 16
- .globl .real_start_of_call
- .thumb_func
- .real_start_of_call:
- push {lr}
- bl __call_via_r0
- pop {r1}
- bx r1
-
- So now both call() and func() can be safely called via
-non-interworking aware ARM code. If, when such a file is assembled,
-the assembler detects the fact that call() is being called by another
-function in the same file, it will automatically adjust the target of
-the BL instruction to point to .real_start_of_call. In this way there
-is no need for the linker to generate a Thumb-to-ARM calling stub so
-that call can be entered in ARM mode.
-
-
-10. How to use dlltool to build ARM/Thumb DLLs
-==============================================
- Given a program (`prog.c') like this:
-
- extern int func_in_dll (void);
-
- int main (void) { return func_in_dll(); }
-
- And a DLL source file (`dll.c') like this:
-
- int func_in_dll (void) { return 1; }
-
- Here is how to build the DLL and the program for a purely ARM based
-environment:
-
-*Step One
- Build a `.def' file describing the DLL:
-
- ; example.def
- ; This file describes the contents of the DLL
- LIBRARY example
- HEAPSIZE 0x40000, 0x2000
- EXPORTS
- func_in_dll 1
-
-*Step Two
- Compile the DLL source code:
-
- arm-pe-gcc -O2 -c dll.c
-
-*Step Three
- Use `dlltool' to create an exports file and a library file:
-
- dlltool --def example.def --output-exp example.o --output-lib example.a
-
-*Step Four
- Link together the complete DLL:
-
- arm-pe-ld dll.o example.o -o example.dll
-
-*Step Five
- Compile the program's source code:
-
- arm-pe-gcc -O2 -c prog.c
-
-*Step Six
- Link together the program and the DLL's library file:
-
- arm-pe-gcc prog.o example.a -o prog
-
- If instead this was a Thumb DLL being called from an ARM program, the
-steps would look like this. (To save space only those steps that are
-different from the previous version are shown):
-
-*Step Two
- Compile the DLL source code (using the Thumb compiler):
-
- thumb-pe-gcc -O2 -c dll.c -mthumb-interwork
-
-*Step Three
- Build the exports and library files (and support interworking):
-
- dlltool -d example.def -z example.o -l example.a --interwork -m thumb
-
-*Step Five
- Compile the program's source code (and support interworking):
-
- arm-pe-gcc -O2 -c prog.c -mthumb-interwork
-
- If instead, the DLL was an old, ARM DLL which does not support
-interworking, and which cannot be rebuilt, then these steps would be
-used.
-
-*Step One
- Skip. If you do not have access to the sources of a DLL, there is
- no point in building a `.def' file for it.
-
-*Step Two
- Skip. With no DLL sources there is nothing to compile.
-
-*Step Three
- Skip. Without a `.def' file you cannot use dlltool to build an
- exports file or a library file.
-
-*Step Four
- Skip. Without a set of DLL object files you cannot build the DLL.
- Besides it has already been built for you by somebody else.
-
-*Step Five
- Compile the program's source code, this is the same as before:
-
- arm-pe-gcc -O2 -c prog.c
-
-*Step Six
- Link together the program and the DLL's library file, passing the
- `--support-old-code' option to the linker:
-
- arm-pe-gcc prog.o example.a -Wl,--support-old-code -o prog
-
- Ignore the warning message about the input file not supporting
- interworking as the --support-old-code switch has taken care if this.
diff --git a/gcc/config/arm/lib1thumb.asm b/gcc/config/arm/lib1thumb.asm
deleted file mode 100755
index e0ff746..0000000
--- a/gcc/config/arm/lib1thumb.asm
+++ /dev/null
@@ -1,736 +0,0 @@
-@ libgcc1 routines for ARM cpu.
-@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
-
-/* Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc.
-
-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. */
-
- .code 16
-
-#ifdef __elf__
-#define __PLT__ (PLT)
-#define TYPE(x) .type SYM(x),function
-#define SIZE(x) .size SYM(x), . - SYM(x)
-#else
-#define __PLT__
-#define TYPE(x)
-#define SIZE(x)
-#endif
-
-#define RET mov pc, lr
-
-#define SYM(x) x
-
-work .req r4 @ XXXX is this safe ?
-
-#ifdef L_udivsi3
-
-dividend .req r0
-divisor .req r1
-result .req r2
-curbit .req r3
-ip .req r12
-sp .req r13
-lr .req r14
-pc .req r15
-
- .text
- .globl SYM (__udivsi3)
- TYPE (__udivsi3)
- .align 0
- .thumb_func
-SYM (__udivsi3):
- cmp divisor, #0
- beq Ldiv0
- mov curbit, #1
- mov result, #0
-
- push { work }
- cmp dividend, divisor
- bcc Lgot_result
-
- @ Load the constant 0x10000000 into our work register
- mov work, #1
- lsl work, #28
-Loop1:
- @ Unless the divisor is very big, shift it up in multiples of
- @ four bits, since this is the amount of unwinding in the main
- @ division loop. Continue shifting until the divisor is
- @ larger than the dividend.
- cmp divisor, work
- bcs Lbignum
- cmp divisor, dividend
- bcs Lbignum
- lsl divisor, #4
- lsl curbit, #4
- b Loop1
-
-Lbignum:
- @ Set work to 0x80000000
- lsl work, #3
-Loop2:
- @ For very big divisors, we must shift it a bit at a time, or
- @ we will be in danger of overflowing.
- cmp divisor, work
- bcs Loop3
- cmp divisor, dividend
- bcs Loop3
- lsl divisor, #1
- lsl curbit, #1
- b Loop2
-
-Loop3:
- @ Test for possible subtractions, and note which bits
- @ are done in the result. On the final pass, this may subtract
- @ too much from the dividend, but the result will be ok, since the
- @ "bit" will have been shifted out at the bottom.
- cmp dividend, divisor
- bcc Over1
- sub dividend, dividend, divisor
- orr result, result, curbit
-Over1:
- lsr work, divisor, #1
- cmp dividend, work
- bcc Over2
- sub dividend, dividend, work
- lsr work, curbit, #1
- orr result, work
-Over2:
- lsr work, divisor, #2
- cmp dividend, work
- bcc Over3
- sub dividend, dividend, work
- lsr work, curbit, #2
- orr result, work
-Over3:
- lsr work, divisor, #3
- cmp dividend, work
- bcc Over4
- sub dividend, dividend, work
- lsr work, curbit, #3
- orr result, work
-Over4:
- cmp dividend, #0 @ Early termination?
- beq Lgot_result
- lsr curbit, #4 @ No, any more bits to do?
- beq Lgot_result
- lsr divisor, #4
- b Loop3
-Lgot_result:
- mov r0, result
- pop { work }
- RET
-
-Ldiv0:
- push { lr }
- bl SYM (__div0) __PLT__
- mov r0, #0 @ about as wrong as it could be
- pop { pc }
-
- SIZE (__udivsi3)
-
-#endif /* L_udivsi3 */
-
-#ifdef L_umodsi3
-
-dividend .req r0
-divisor .req r1
-overdone .req r2
-curbit .req r3
-ip .req r12
-sp .req r13
-lr .req r14
-pc .req r15
-
- .text
- .globl SYM (__umodsi3)
- TYPE (__umodsi3)
- .align 0
- .thumb_func
-SYM (__umodsi3):
- cmp divisor, #0
- beq Ldiv0
- mov curbit, #1
- cmp dividend, divisor
- bcs Over1
- RET
-
-Over1:
- @ Load the constant 0x10000000 into our work register
- push { work }
- mov work, #1
- lsl work, #28
-Loop1:
- @ Unless the divisor is very big, shift it up in multiples of
- @ four bits, since this is the amount of unwinding in the main
- @ division loop. Continue shifting until the divisor is
- @ larger than the dividend.
- cmp divisor, work
- bcs Lbignum
- cmp divisor, dividend
- bcs Lbignum
- lsl divisor, #4
- lsl curbit, #4
- b Loop1
-
-Lbignum:
- @ Set work to 0x80000000
- lsl work, #3
-Loop2:
- @ For very big divisors, we must shift it a bit at a time, or
- @ we will be in danger of overflowing.
- cmp divisor, work
- bcs Loop3
- cmp divisor, dividend
- bcs Loop3
- lsl divisor, #1
- lsl curbit, #1
- b Loop2
-
-Loop3:
- @ Test for possible subtractions. On the final pass, this may
- @ subtract too much from the dividend, so keep track of which
- @ subtractions are done, we can fix them up afterwards...
- mov overdone, #0
- cmp dividend, divisor
- bcc Over2
- sub dividend, dividend, divisor
-Over2:
- lsr work, divisor, #1
- cmp dividend, work
- bcc Over3
- sub dividend, dividend, work
- mov ip, curbit
- mov work, #1
- ror curbit, work
- orr overdone, curbit
- mov curbit, ip
-Over3:
- lsr work, divisor, #2
- cmp dividend, work
- bcc Over4
- sub dividend, dividend, work
- mov ip, curbit
- mov work, #2
- ror curbit, work
- orr overdone, curbit
- mov curbit, ip
-Over4:
- lsr work, divisor, #3
- cmp dividend, work
- bcc Over5
- sub dividend, dividend, work
- mov ip, curbit
- mov work, #3
- ror curbit, work
- orr overdone, curbit
- mov curbit, ip
-Over5:
- mov ip, curbit
- cmp dividend, #0 @ Early termination?
- beq Over6
- lsr curbit, #4 @ No, any more bits to do?
- beq Over6
- lsr divisor, #4
- b Loop3
-
-Over6:
- @ Any subtractions that we should not have done will be recorded in
- @ the top three bits of "overdone". Exactly which were not needed
- @ are governed by the position of the bit, stored in ip.
- @ If we terminated early, because dividend became zero,
- @ then none of the below will match, since the bit in ip will not be
- @ in the bottom nibble.
-
- mov work, #0xe
- lsl work, #28
- and overdone, work
- bne Over7
- pop { work }
- RET @ No fixups needed
-Over7:
- mov curbit, ip
- mov work, #3
- ror curbit, work
- tst overdone, curbit
- beq Over8
- lsr work, divisor, #3
- add dividend, dividend, work
-Over8:
- mov curbit, ip
- mov work, #2
- ror curbit, work
- tst overdone, curbit
- beq Over9
- lsr work, divisor, #2
- add dividend, dividend, work
-Over9:
- mov curbit, ip
- mov work, #1
- ror curbit, work
- tst overdone, curbit
- beq Over10
- lsr work, divisor, #1
- add dividend, dividend, work
-Over10:
- pop { work }
- RET
-
-Ldiv0:
- push { lr }
- bl SYM (__div0) __PLT__
- mov r0, #0 @ about as wrong as it could be
- pop { pc }
-
- SIZE (__umodsi3)
-
-#endif /* L_umodsi3 */
-
-#ifdef L_divsi3
-
-dividend .req r0
-divisor .req r1
-result .req r2
-curbit .req r3
-ip .req r12
-sp .req r13
-lr .req r14
-pc .req r15
-
- .text
- .globl SYM (__divsi3)
- TYPE (__divsi3)
- .align 0
- .thumb_func
-SYM (__divsi3):
- cmp divisor, #0
- beq Ldiv0
-
- push { work }
- mov work, dividend
- eor work, divisor @ Save the sign of the result.
- mov ip, work
- mov curbit, #1
- mov result, #0
- cmp divisor, #0
- bpl Over1
- neg divisor, divisor @ Loops below use unsigned.
-Over1:
- cmp dividend, #0
- bpl Over2
- neg dividend, dividend
-Over2:
- cmp dividend, divisor
- bcc Lgot_result
-
- mov work, #1
- lsl work, #28
-Loop1:
- @ Unless the divisor is very big, shift it up in multiples of
- @ four bits, since this is the amount of unwinding in the main
- @ division loop. Continue shifting until the divisor is
- @ larger than the dividend.
- cmp divisor, work
- Bcs Lbignum
- cmp divisor, dividend
- Bcs Lbignum
- lsl divisor, #4
- lsl curbit, #4
- b Loop1
-
-Lbignum:
- @ For very big divisors, we must shift it a bit at a time, or
- @ we will be in danger of overflowing.
- lsl work, #3
-Loop2:
- cmp divisor, work
- Bcs Loop3
- cmp divisor, dividend
- Bcs Loop3
- lsl divisor, #1
- lsl curbit, #1
- b Loop2
-
-Loop3:
- @ Test for possible subtractions, and note which bits
- @ are done in the result. On the final pass, this may subtract
- @ too much from the dividend, but the result will be ok, since the
- @ "bit" will have been shifted out at the bottom.
- cmp dividend, divisor
- Bcc Over3
- sub dividend, dividend, divisor
- orr result, result, curbit
-Over3:
- lsr work, divisor, #1
- cmp dividend, work
- Bcc Over4
- sub dividend, dividend, work
- lsr work, curbit, #1
- orr result, work
-Over4:
- lsr work, divisor, #2
- cmp dividend, work
- Bcc Over5
- sub dividend, dividend, work
- lsr work, curbit, #2
- orr result, result, work
-Over5:
- lsr work, divisor, #3
- cmp dividend, work
- Bcc Over6
- sub dividend, dividend, work
- lsr work, curbit, #3
- orr result, result, work
-Over6:
- cmp dividend, #0 @ Early termination?
- Beq Lgot_result
- lsr curbit, #4 @ No, any more bits to do?
- Beq Lgot_result
- lsr divisor, #4
- b Loop3
-
-Lgot_result:
- mov r0, result
- mov work, ip
- cmp work, #0
- Bpl Over7
- neg r0, r0
-Over7:
- pop { work }
- RET
-
-Ldiv0:
- push { lr }
- bl SYM (__div0) __PLT__
- mov r0, #0 @ about as wrong as it could be
- pop { pc }
-
- SIZE (__divsi3)
-
-#endif /* L_divsi3 */
-
-#ifdef L_modsi3
-
-dividend .req r0
-divisor .req r1
-overdone .req r2
-curbit .req r3
-ip .req r12
-sp .req r13
-lr .req r14
-pc .req r15
-
- .text
- .globl SYM (__modsi3)
- TYPE (__modsi3)
- .align 0
- .thumb_func
-SYM (__modsi3):
- mov curbit, #1
- cmp divisor, #0
- beq Ldiv0
- Bpl Over1
- neg divisor, divisor @ Loops below use unsigned.
-Over1:
- push { work }
- @ Need to save the sign of the dividend, unfortunately, we need
- @ ip later on. Must do this after saving the original value of
- @ the work register, because we will pop this value off first.
- push { dividend }
- cmp dividend, #0
- Bpl Over2
- neg dividend, dividend
-Over2:
- cmp dividend, divisor
- bcc Lgot_result
- mov work, #1
- lsl work, #28
-Loop1:
- @ Unless the divisor is very big, shift it up in multiples of
- @ four bits, since this is the amount of unwinding in the main
- @ division loop. Continue shifting until the divisor is
- @ larger than the dividend.
- cmp divisor, work
- bcs Lbignum
- cmp divisor, dividend
- bcs Lbignum
- lsl divisor, #4
- lsl curbit, #4
- b Loop1
-
-Lbignum:
- @ Set work to 0x80000000
- lsl work, #3
-Loop2:
- @ For very big divisors, we must shift it a bit at a time, or
- @ we will be in danger of overflowing.
- cmp divisor, work
- bcs Loop3
- cmp divisor, dividend
- bcs Loop3
- lsl divisor, #1
- lsl curbit, #1
- b Loop2
-
-Loop3:
- @ Test for possible subtractions. On the final pass, this may
- @ subtract too much from the dividend, so keep track of which
- @ subtractions are done, we can fix them up afterwards...
- mov overdone, #0
- cmp dividend, divisor
- bcc Over3
- sub dividend, dividend, divisor
-Over3:
- lsr work, divisor, #1
- cmp dividend, work
- bcc Over4
- sub dividend, dividend, work
- mov ip, curbit
- mov work, #1
- ror curbit, work
- orr overdone, curbit
- mov curbit, ip
-Over4:
- lsr work, divisor, #2
- cmp dividend, work
- bcc Over5
- sub dividend, dividend, work
- mov ip, curbit
- mov work, #2
- ror curbit, work
- orr overdone, curbit
- mov curbit, ip
-Over5:
- lsr work, divisor, #3
- cmp dividend, work
- bcc Over6
- sub dividend, dividend, work
- mov ip, curbit
- mov work, #3
- ror curbit, work
- orr overdone, curbit
- mov curbit, ip
-Over6:
- mov ip, curbit
- cmp dividend, #0 @ Early termination?
- beq Over7
- lsr curbit, #4 @ No, any more bits to do?
- beq Over7
- lsr divisor, #4
- b Loop3
-
-Over7:
- @ Any subtractions that we should not have done will be recorded in
- @ the top three bits of "overdone". Exactly which were not needed
- @ are governed by the position of the bit, stored in ip.
- @ If we terminated early, because dividend became zero,
- @ then none of the below will match, since the bit in ip will not be
- @ in the bottom nibble.
- mov work, #0xe
- lsl work, #28
- and overdone, work
- beq Lgot_result
-
- mov curbit, ip
- mov work, #3
- ror curbit, work
- tst overdone, curbit
- beq Over8
- lsr work, divisor, #3
- add dividend, dividend, work
-Over8:
- mov curbit, ip
- mov work, #2
- ror curbit, work
- tst overdone, curbit
- beq Over9
- lsr work, divisor, #2
- add dividend, dividend, work
-Over9:
- mov curbit, ip
- mov work, #1
- ror curbit, work
- tst overdone, curbit
- beq Lgot_result
- lsr work, divisor, #1
- add dividend, dividend, work
-Lgot_result:
- pop { work }
- cmp work, #0
- bpl Over10
- neg dividend, dividend
-Over10:
- pop { work }
- RET
-
-Ldiv0:
- push { lr }
- bl SYM (__div0) __PLT__
- mov r0, #0 @ about as wrong as it could be
- pop { pc }
-
- SIZE (__modsi3)
-
-#endif /* L_modsi3 */
-
-#ifdef L_dvmd_tls
-
- .globl SYM (__div0)
- TYPE (__div0)
- .align 0
- .thumb_func
-SYM (__div0):
- RET
-
- SIZE (__div0)
-
-#endif /* L_divmodsi_tools */
-
-
-#ifdef L_call_via_rX
-
-/* These labels & instructions are used by the Arm/Thumb interworking code.
- The address of function to be called is loaded into a register and then
- one of these labels is called via a BL instruction. This puts the
- return address into the link register with the bottom bit set, and the
- code here switches to the correct mode before executing the function. */
-
- .text
- .align 0
-
-.macro call_via register
- .globl SYM (_call_via_\register)
- TYPE (_call_via_\register)
- .thumb_func
-SYM (_call_via_\register):
- bx \register
- nop
-
- SIZE (_call_via_\register)
-.endm
-
- call_via r0
- call_via r1
- call_via r2
- call_via r3
- call_via r4
- call_via r5
- call_via r6
- call_via r7
- call_via r8
- call_via r9
- call_via sl
- call_via fp
- call_via ip
- call_via sp
- call_via lr
-
-#endif /* L_call_via_rX */
-
-#ifdef L_interwork_call_via_rX
-
-/* These labels & instructions are used by the Arm/Thumb interworking code,
- when the target address is in an unknown instruction set. The address
- of function to be called is loaded into a register and then one of these
- labels is called via a BL instruction. This puts the return address
- into the link register with the bottom bit set, and the code here
- switches to the correct mode before executing the function. Unfortunately
- the target code cannot be relied upon to return via a BX instruction, so
- instead we have to store the resturn address on the stack and allow the
- called function to return here instead. Upon return we recover the real
- return address and use a BX to get back to Thumb mode. */
-
- .text
- .align 0
-
- .code 32
- .globl _arm_return
-_arm_return:
- ldmia r13!, {r12}
- bx r12
-
-.macro interwork register
- .code 16
-
- .globl SYM (_interwork_call_via_\register)
- TYPE (_interwork_call_via_\register)
- .thumb_func
-SYM (_interwork_call_via_\register):
- bx pc
- nop
-
- .code 32
- .globl .Lchange_\register
-.Lchange_\register:
- tst \register, #1
- stmeqdb r13!, {lr}
- adreq lr, _arm_return
- bx \register
-
- SIZE (_interwork_call_via_\register)
-.endm
-
- interwork r0
- interwork r1
- interwork r2
- interwork r3
- interwork r4
- interwork r5
- interwork r6
- interwork r7
- interwork r8
- interwork r9
- interwork sl
- interwork fp
- interwork ip
- interwork sp
-
- /* The lr case has to be handled a little differently...*/
- .code 16
- .globl SYM (_interwork_call_via_lr)
- TYPE (_interwork_call_via_lr)
- .thumb_func
-SYM (_interwork_call_via_lr):
- bx pc
- nop
-
- .code 32
- .globl .Lchange_lr
-.Lchange_lr:
- tst lr, #1
- stmeqdb r13!, {lr}
- mov ip, lr
- adreq lr, _arm_return
- bx ip
-
- SIZE (_interwork_call_via_lr)
-
-#endif /* L_interwork_call_via_rX */
diff --git a/gcc/config/arm/t-thumb-elf b/gcc/config/arm/t-thumb-elf
deleted file mode 100755
index 3e940f8..0000000
--- a/gcc/config/arm/t-thumb-elf
+++ /dev/null
@@ -1,32 +0,0 @@
-# CYGNUS LOCAL (entire file) clm/arm-elf
-CROSS_LIBGCC1 = libgcc1-asm.a
-LIB1ASMSRC = arm/lib1thumb.asm
-LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _call_via_rX _interwork_call_via_rX
-# adddi3/subdi3 added to machine description
-
-# These are really part of libgcc1, but this will cause them to be
-# built correctly, so...
-
-LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c
-
-fp-bit.c: $(srcdir)/config/fp-bit.c
- echo '#define FLOAT' > fp-bit.c
- echo '#ifndef __ARMEB__' >> fp-bit.c
- echo '#define FLOAT_BIT_ORDER_MISMATCH' >> fp-bit.c
- echo '#endif' >> fp-bit.c
- cat $(srcdir)/config/fp-bit.c >> fp-bit.c
-
-dp-bit.c: $(srcdir)/config/fp-bit.c
- echo '#ifndef __ARMEB__' > dp-bit.c
- echo '#define FLOAT_BIT_ORDER_MISMATCH' >> dp-bit.c
- echo '#define FLOAT_WORD_ORDER_MISMATCH' >> dp-bit.c
- echo '#endif' >> dp-bit.c
- cat $(srcdir)/config/fp-bit.c >> dp-bit.c
-
-# Avoid building a duplicate set of libraries for the default endian-ness.
-MULTILIB_OPTIONS = mno-thumb-interwork/mthumb-interwork
-MULTILIB_DIRNAMES = normal interwork
-MULTILIB_MATCHES =
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/arm/telf.h b/gcc/config/arm/telf.h
deleted file mode 100755
index 9bd6bcf..0000000
--- a/gcc/config/arm/telf.h
+++ /dev/null
@@ -1,368 +0,0 @@
-/* CYGNUS LOCAL (entire file) clm/arm-elf */
-/* Definitions of target machine for GNU compiler,
- for Thumb with ELF obj format.
- Copyright (C) 1995, 1996 Free Software Foundation, Inc.
-
-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. */
-
-#define OBJECT_FORMAT_ELF
-
-#include "arm/thumb.h"
-#include "tree.h"
-
-/* Run-time Target Specification. */
-#undef TARGET_VERSION
-#define TARGET_VERSION fputs (" (Thumb/elf)", stderr)
-
-#define MULTILIB_DEFAULTS { "mlittle-endian" }
-
-/* Setting this to 32 produces more efficient code, but the value set in previous
- versions of this toolchain was 8, which produces more compact structures. The
- command line option -mstructure_size_boundary=<n> can be used to change this
- value. */
-#undef STRUCTURE_SIZE_BOUNDARY
-#define STRUCTURE_SIZE_BOUNDARY arm_structure_size_boundary
-
-extern int arm_structure_size_boundary;
-
-/* Debug */
-#define DWARF2_DEBUGGING_INFO
-
-
-/* Note - it is important that these definitions match those in semi.h for the ARM port. */
-#undef LOCAL_LABEL_PREFIX
-#define LOCAL_LABEL_PREFIX "."
-
-
-/* A C statement to output assembler commands which will identify the
- object file as having been compiled with GNU CC (or another GNU
- compiler). */
-#define ASM_IDENTIFY_GCC(STREAM) \
- fprintf (STREAM, "%sgcc2_compiled.:\n", LOCAL_LABEL_PREFIX )
-
-#undef ASM_FILE_START
-#define ASM_FILE_START(STREAM) \
-do { \
- extern char *version_string; \
- fprintf ((STREAM), "%s Generated by gcc %s for Thumb/elf\n", \
- ASM_COMMENT_START, version_string); \
- fprintf ((STREAM), ASM_APP_OFF); \
-} while (0)
-
-/* A C statement to output something to the assembler file to switch to section
- NAME for object DECL which is either a FUNCTION_DECL, a VAR_DECL or
- NULL_TREE. Some target formats do not support arbitrary sections. Do not
- define this macro in such cases. */
-#define ASM_OUTPUT_SECTION_NAME(STREAM, DECL, NAME, RELOC) \
-do { \
- if ((DECL) && TREE_CODE (DECL) == FUNCTION_DECL) \
- fprintf (STREAM, "\t.section %s,\"ax\",%%progbits\n", (NAME)); \
- else if ((DECL) && DECL_READONLY_SECTION (DECL, RELOC)) \
- fprintf (STREAM, "\t.section %s,\"a\"\n", (NAME)); \
- else if (0 == strncmp((NAME), ".bss", sizeof(".bss") - 1)) \
- fprintf (STREAM, "\t.section %s,\"aw\",%%nobits\n", (NAME)); \
- else \
- fprintf (STREAM, "\t.section %s,\"aw\"\n", (NAME)); \
-} while (0)
-
-#undef INIT_SECTION_ASM_OP
-
-/* Define this macro if jump tables (for `tablejump' insns) should be
- output in the text section, along with the assembler instructions.
- Otherwise, the readonly data section is used. */
-#define JUMP_TABLES_IN_TEXT_SECTION 1
-
-#undef READONLY_DATA_SECTION
-#define READONLY_DATA_SECTION rdata_section
-#undef RDATA_SECTION_ASM_OP
-#define RDATA_SECTION_ASM_OP "\t.section .rodata"
-
-/* If defined, a C expression whose value is a string containing the
- assembler operation to identify the following data as
- uninitialized global data. If not defined, and neither
- `ASM_OUTPUT_BSS' nor `ASM_OUTPUT_ALIGNED_BSS' are defined,
- uninitialized global data will be output in the data section if
- `-fno-common' is passed, otherwise `ASM_OUTPUT_COMMON' will be
- used. */
-#ifndef BSS_SECTION_ASM_OP
-#define BSS_SECTION_ASM_OP ".section\t.bss"
-#endif
-
-/* Like `ASM_OUTPUT_BSS' except takes the required alignment as a
- separate, explicit argument. If you define this macro, it is used
- in place of `ASM_OUTPUT_BSS', and gives you more flexibility in
- handling the required alignment of the variable. The alignment is
- specified as the number of bits.
-
- Try to use function `asm_output_aligned_bss' defined in file
- `varasm.c' when defining this macro. */
-#ifndef ASM_OUTPUT_ALIGNED_BSS
-#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
- asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
-#endif
-
-/* Don't know how to order these. UNALIGNED_WORD_ASM_OP is in
- dwarf2.out. */
-#define UNALIGNED_WORD_ASM_OP ".4byte"
-
-#define ASM_OUTPUT_DWARF2_ADDR_CONST(FILE,ADDR) \
- if (((ADDR)[0] == '.') && ((ADDR)[1] == 'L')) \
- fprintf ((FILE), "\t%s\t%s", UNALIGNED_WORD_ASM_OP, (ADDR)); \
- else \
- fprintf ((FILE), "\t%s\t%s", \
- UNALIGNED_WORD_ASM_OP, (ADDR))
-
-#define ASM_OUTPUT_DWARF_ADDR_CONST(FILE,RTX) \
-do { \
- fprintf ((FILE), "\t%s\t", UNALIGNED_WORD_ASM_OP); \
- output_addr_const ((FILE), (RTX)); \
- fputc ('\n', (FILE)); \
-} while (0)
-
-/* This is how to equate one symbol to another symbol. The syntax used is
- `SYM1=SYM2'. Note that this is different from the way equates are done
- with most svr4 assemblers, where the syntax is `.set SYM1,SYM2'. */
-
-#define ASM_OUTPUT_DEF(FILE,LABEL1,LABEL2) \
- do { fprintf ((FILE), "\t"); \
- assemble_name (FILE, LABEL1); \
- fprintf (FILE, " = "); \
- assemble_name (FILE, LABEL2); \
- fprintf (FILE, "\n"); \
- } while (0)
-
-/* For aliases of functions we use .thumb_set instead. */
-#define ASM_OUTPUT_DEF_FROM_DECLS(FILE,DECL1,DECL2) \
- do \
- { \
- char * LABEL1 = XSTR (XEXP (DECL_RTL (decl), 0), 0); \
- char * LABEL2 = IDENTIFIER_POINTER (DECL2); \
- \
- if (TREE_CODE (DECL1) == FUNCTION_DECL) \
- { \
- fprintf (FILE, "\t.thumb_set "); \
- assemble_name (FILE, LABEL1); \
- fprintf (FILE, ","); \
- assemble_name (FILE, LABEL2); \
- fprintf (FILE, "\n"); \
- } \
- else \
- ASM_OUTPUT_DEF (FILE, LABEL1, LABEL2); \
- } \
- while (0)
-
-/* A list of other sections which the compiler might be "in" at any
- given time. */
-#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_rdata
-
-/* A list of extra section function definitions. */
-
-#undef EXTRA_SECTION_FUNCTIONS
-#define EXTRA_SECTION_FUNCTIONS \
- RDATA_SECTION_FUNCTION
-
-#define RDATA_SECTION_FUNCTION \
-void \
-rdata_section () \
-{ \
- if (in_section != in_rdata) \
- { \
- fprintf (asm_out_file, "%s\n", RDATA_SECTION_ASM_OP); \
- in_section = in_rdata; \
- } \
-}
-
-#define INT_ASM_OP ".word"
-
-#define INVOKE__main
-
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC "crtbegin%O%s crt0%O%s"
-
-#undef ENDFILE_SPEC
-#define ENDFILE_SPEC "crtend%O%s"
-
-/* A C expression whose value is nonzero if IDENTIFIER with arguments ARGS
- is a valid machine specific attribute for DECL.
- The attributes in ATTRIBUTES have previously been assigned to DECL. */
-extern int arm_valid_machine_decl_attribute(tree decl, tree attributes, tree attr, tree args);
-#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \
- arm_valid_machine_decl_attribute(DECL, ATTRIBUTES, IDENTIFIER, ARGS)
-
-/* The ARM development system defines __main. */
-#define NAME__MAIN "__gccmain"
-#define SYMBOL__MAIN __gccmain
-
-#define UNIQUE_SECTION_P(DECL) (DECL_ONE_ONLY (DECL))
-#define UNIQUE_SECTION(DECL,RELOC) \
-do { \
- int len; \
- char * name, * string, * prefix; \
- \
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (DECL)); \
- \
- if (! DECL_ONE_ONLY (DECL)) \
- { \
- prefix = "."; \
- if (TREE_CODE (DECL) == FUNCTION_DECL) \
- prefix = ".text."; \
- else if (DECL_READONLY_SECTION (DECL, RELOC)) \
- prefix = ".rodata."; \
- else \
- prefix = ".data."; \
- } \
- else if (TREE_CODE (DECL) == FUNCTION_DECL) \
- prefix = ".gnu.linkonce.t."; \
- else if (DECL_READONLY_SECTION (DECL, RELOC)) \
- prefix = ".gnu.linkonce.r."; \
- else \
- prefix = ".gnu.linkonce.d."; \
- \
- len = strlen (name) + strlen (prefix); \
- string = alloca (len + 1); \
- sprintf (string, "%s%s", prefix, name); \
- \
- DECL_SECTION_NAME (DECL) = build_string (len, string); \
-} while (0)
-
-/* This is how we tell the assembler that a symbol is weak. */
-#ifndef ASM_WEAKEN_LABEL
-#define ASM_WEAKEN_LABEL(FILE, NAME) \
- do \
- { \
- fputs ("\t.weak\t", FILE); \
- assemble_name (FILE, NAME); \
- fputc ('\n', FILE); \
- } \
- while (0)
-#endif
-
-#ifndef TYPE_ASM_OP
-
-/* These macros generate the special .type and .size directives which
- are used to set the corresponding fields of the linker symbol table
- entries in an ELF object file under SVR4. These macros also output
- the starting labels for the relevant functions/objects. */
-#define TYPE_ASM_OP ".type"
-#define SIZE_ASM_OP ".size"
-
-/* The following macro defines the format used to output the second
- operand of the .type assembler directive. Different svr4 assemblers
- expect various different forms for this operand. The one given here
- is just a default. You may need to override it in your machine-
- specific tm.h file (depending upon the particulars of your assembler). */
-#define TYPE_OPERAND_FMT "%s"
-
-/* Write the extra assembler code needed to declare a function's result.
- Most svr4 assemblers don't require any special declaration of the
- result value, but there are exceptions. */
-#ifndef ASM_DECLARE_RESULT
-#define ASM_DECLARE_RESULT(FILE, RESULT)
-#endif
-
-/* Write the extra assembler code needed to declare a function properly.
- Some svr4 assemblers need to also have something extra said about the
- function's return value. We allow for that here. */
-#undef ASM_DECLARE_FUNCTION_NAME
-#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
- do \
- { \
- fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \
- assemble_name (FILE, NAME); \
- putc (',', FILE); \
- fprintf (FILE, TYPE_OPERAND_FMT, "function"); \
- putc ('\n', FILE); \
- ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
- fprintf (FILE, "\t.thumb_func\n") ; \
- ASM_OUTPUT_LABEL(FILE, NAME); \
- } \
- while (0)
-
-/* Write the extra assembler code needed to declare an object properly. */
-#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
- do \
- { \
- fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \
- assemble_name (FILE, NAME); \
- putc (',', FILE); \
- fprintf (FILE, TYPE_OPERAND_FMT, "object"); \
- putc ('\n', FILE); \
- size_directive_output = 0; \
- if (!flag_inhibit_size_directive && DECL_SIZE (DECL)) \
- { \
- size_directive_output = 1; \
- fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
- assemble_name (FILE, NAME); \
- putc (',', FILE); \
- fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, \
- int_size_in_bytes (TREE_TYPE (DECL))); \
- fputc ('\n', FILE); \
- } \
- ASM_OUTPUT_LABEL(FILE, NAME); \
- } \
- while (0)
-
-/* Output the size directive for a decl in rest_of_decl_compilation
- in the case where we did not do so before the initializer.
- Once we find the error_mark_node, we know that the value of
- size_directive_output was set
- by ASM_DECLARE_OBJECT_NAME when it was run for the same decl. */
-#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \
- do \
- { \
- char * name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \
- if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \
- && ! AT_END && TOP_LEVEL \
- && DECL_INITIAL (DECL) == error_mark_node \
- && !size_directive_output) \
- { \
- size_directive_output = 1; \
- fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
- assemble_name (FILE, name); \
- putc (',', FILE); \
- fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, \
- int_size_in_bytes (TREE_TYPE (DECL))); \
- fputc ('\n', FILE); \
- } \
- } \
- while (0)
-
-/* This is how to declare the size of a function. */
-#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
- do \
- { \
- if (!flag_inhibit_size_directive) \
- { \
- char label[256]; \
- static int labelno; \
- labelno ++; \
- ASM_GENERATE_INTERNAL_LABEL (label, "Lfe", labelno); \
- ASM_OUTPUT_INTERNAL_LABEL (FILE, "Lfe", labelno); \
- fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
- assemble_name (FILE, (FNAME)); \
- fprintf (FILE, ","); \
- assemble_name (FILE, label); \
- fprintf (FILE, "-"); \
- assemble_name (FILE, (FNAME)); \
- putc ('\n', FILE); \
- } \
- } \
- while (0)
-
-#endif /* TYPE_ASM_OP */
diff --git a/gcc/config/arm/thumb.c b/gcc/config/arm/thumb.c
deleted file mode 100755
index 0310a51..0000000
--- a/gcc/config/arm/thumb.c
+++ /dev/null
@@ -1,1527 +0,0 @@
-/* Output routines for GCC for ARM/Thumb
- Copyright (C) 1996 Cygnus Software Technologies Ltd
- The basis of this contribution was generated by
- Richard Earnshaw, Advanced RISC Machines Ltd
-
- 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. */
-
-#include <stdio.h>
-#include <string.h>
-#include "config.h"
-#include "rtl.h"
-#include "hard-reg-set.h"
-#include "regs.h"
-#include "output.h"
-#include "insn-flags.h"
-#include "insn-attr.h"
-#include "insn-config.h"
-#include "flags.h"
-#include "tree.h"
-#include "expr.h"
-#include "toplev.h"
-#include "recog.h"
-
-int current_function_anonymous_args = 0;
-static int current_function_has_far_jump = 0;
-
-/* Used to parse -mstructure_size_boundary command line option. */
-char *structure_size_string = NULL;
-int arm_structure_size_boundary = 32; /* Used to be 8 */
-
-/* Predicates */
-
-/* Return nonzero if op is suitable for the RHS of a cmp instruction. */
-int
-thumb_cmp_operand(rtx op, enum machine_mode mode)
-{
- return ((GET_CODE(op) == CONST_INT
- && (HOST_WIDE_UINT) (INTVAL(op)) < 256)
- || register_operand(op, mode));
-}
-
-int
-thumb_shiftable_const(HOST_WIDE_INT val)
-{
- HOST_WIDE_UINT x = val;
- HOST_WIDE_UINT mask = 0xff;
- int i;
-
- for (i = 0; i < 25; i++)
- if ((val & (mask << i)) == val)
- return 1;
-
- return 0;
-}
-
-/* Routines for handling the constant pool */
-/* This is unashamedly hacked from the version in sh.c, since the problem is
- extremely similar. */
-
-/* Thumb instructions cannot load a large constant into a register,
- constants have to come from a pc relative load. The reference of a pc
- relative load instruction must be less than 1k infront of the instruction.
- This means that we often have to dump a constant inside a function, and
- generate code to branch around it.
-
- It is important to minimize this, since the branches will slow things
- down and make things bigger.
-
- Worst case code looks like:
-
- ldr rn, L1
- b L2
- align
- L1: .long value
- L2:
- ..
-
- ldr rn, L3
- b L4
- align
- L3: .long value
- L4:
- ..
-
- We fix this by performing a scan before scheduling, which notices which
- instructions need to have their operands fetched from the constant table
- and builds the table.
-
-
- The algorithm is:
-
- scan, find an instruction which needs a pcrel move. Look forward, find the
- last barrier which is within MAX_COUNT bytes of the requirement.
- If there isn't one, make one. Process all the instructions between
- the find and the barrier.
-
- In the above example, we can tell that L3 is within 1k of L1, so
- the first move can be shrunk from the 2 insn+constant sequence into
- just 1 insn, and the constant moved to L3 to make:
-
- ldr rn, L1
- ..
- ldr rn, L3
- b L4
- align
- L1: .long value
- L3: .long value
- L4:
-
- Then the second move becomes the target for the shortening process.
-
- */
-
-typedef struct
-{
- rtx value; /* Value in table */
- HOST_WIDE_INT next_offset;
- enum machine_mode mode; /* Mode of value */
-} pool_node;
-
-/* The maximum number of constants that can fit into one pool, since
- the pc relative range is 0...1020 bytes and constants are at least 4
- bytes long */
-
-#define MAX_POOL_SIZE (1020/4)
-static pool_node pool_vector[MAX_POOL_SIZE];
-static int pool_size;
-static rtx pool_vector_label;
-
-/* Add a constant to the pool and return its label. */
-
-static HOST_WIDE_INT
-add_constant(rtx x, enum machine_mode mode)
-{
- int i;
- rtx lab;
- HOST_WIDE_INT offset;
-
- if (mode == SImode && GET_CODE(x) == MEM && CONSTANT_P(XEXP(x, 0))
- && CONSTANT_POOL_ADDRESS_P(XEXP(x, 0)))
- x = get_pool_constant(XEXP(x, 0));
-
- /* First see if we've already got it */
-
- for (i = 0; i < pool_size; i++)
- {
- if (x->code == pool_vector[i].value->code
- && mode == pool_vector[i].mode)
- {
- if (x->code == CODE_LABEL)
- {
- if (XINT(x, 3) != XINT(pool_vector[i].value, 3))
- continue;
- }
- if (rtx_equal_p(x, pool_vector[i].value))
- return pool_vector[i].next_offset - GET_MODE_SIZE(mode);
- }
- }
-
- /* Need a new one */
-
- pool_vector[pool_size].next_offset = GET_MODE_SIZE(mode);
- offset = 0;
- if (pool_size == 0)
- pool_vector_label = gen_label_rtx();
- else
- pool_vector[pool_size].next_offset
- += (offset = pool_vector[pool_size - 1].next_offset);
-
- pool_vector[pool_size].value = x;
- pool_vector[pool_size].mode = mode;
- pool_size++;
- return offset;
-}
-
-/* Output the literal table */
-
-static void
-dump_table(rtx scan)
-{
- int i;
-
- scan = emit_label_after(gen_label_rtx(), scan);
- scan = emit_insn_after(gen_align_4(), scan);
- scan = emit_label_after(pool_vector_label, scan);
-
- for (i = 0; i < pool_size; i++)
- {
- pool_node *p = pool_vector + i;
-
- switch (GET_MODE_SIZE(p->mode))
- {
- case 4:
- scan = emit_insn_after(gen_consttable_4(p->value), scan);
- break;
-
- case 8:
- scan = emit_insn_after(gen_consttable_8(p->value), scan);
- break;
-
- default:
- abort();
- break;
- }
- }
-
- scan = emit_insn_after(gen_consttable_end(), scan);
- scan = emit_barrier_after(scan);
- pool_size = 0;
-}
-
-/* Non zero if the src operand needs to be fixed up */
-static
-int
-fixit(rtx src, enum machine_mode mode)
-{
- return ((CONSTANT_P(src)
- && (GET_CODE(src) != CONST_INT
- || !(CONST_OK_FOR_LETTER_P(INTVAL(src), 'I')
- || CONST_OK_FOR_LETTER_P(INTVAL(src), 'J')
- || (mode != DImode
- && CONST_OK_FOR_LETTER_P(INTVAL(src), 'K')))))
- || (mode == SImode && GET_CODE(src) == MEM
- && GET_CODE(XEXP(src, 0)) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P(XEXP(src, 0))));
-}
-
-/* Find the last barrier less than MAX_COUNT bytes from FROM, or create one. */
-
-#define MAX_COUNT_SI 1000
-
-static rtx
-find_barrier(rtx from)
-{
- int count = 0;
- rtx found_barrier = 0;
- rtx label;
-
- while (from && count < MAX_COUNT_SI)
- {
- if (GET_CODE(from) == BARRIER)
- return from;
-
- /* Count the length of this insn */
- if (GET_CODE(from) == INSN
- && GET_CODE(PATTERN(from)) == SET
- && CONSTANT_P(SET_SRC(PATTERN(from)))
- && CONSTANT_POOL_ADDRESS_P(SET_SRC(PATTERN(from))))
- {
- rtx src = SET_SRC(PATTERN(from));
- count += 2;
- }
- else
- count += get_attr_length(from);
-
- from = NEXT_INSN(from);
- }
-
- /* We didn't find a barrier in time to
- dump our stuff, so we'll make one */
- label = gen_label_rtx();
-
- if (from)
- from = PREV_INSN(from);
- else
- from = get_last_insn();
-
- /* Walk back to be just before any jump */
- while (GET_CODE(from) == JUMP_INSN
- || GET_CODE(from) == NOTE
- || GET_CODE(from) == CODE_LABEL)
- from = PREV_INSN(from);
-
- from = emit_jump_insn_after(gen_jump(label), from);
- JUMP_LABEL(from) = label;
- found_barrier = emit_barrier_after(from);
- emit_label_after(label, found_barrier);
- return found_barrier;
-}
-
-/* Non zero if the insn is a move instruction which needs to be fixed. */
-
-static int
-broken_move(rtx insn)
-{
- if (!INSN_DELETED_P(insn)
- && GET_CODE(insn) == INSN
- && GET_CODE(PATTERN(insn)) == SET)
- {
- rtx pat = PATTERN(insn);
- rtx src = SET_SRC(pat);
- rtx dst = SET_DEST(pat);
- enum machine_mode mode = GET_MODE(dst);
- if (dst == pc_rtx)
- return 0;
- return fixit(src, mode);
- }
- return 0;
-}
-
-/* Recursively search through all of the blocks in a function
- checking to see if any of the variables created in that
- function match the RTX called 'orig'. If they do then
- replace them with the RTX called 'replacement'. */
-
-static void
-replace_symbols_in_block(tree block, rtx orig, rtx replacement)
-{
- for (; block; block = BLOCK_CHAIN(block))
- {
- tree sym;
-
- if (!TREE_USED(block))
- continue;
-
- for (sym = BLOCK_VARS(block); sym; sym = TREE_CHAIN(sym))
- {
- if ( (DECL_NAME(sym) == 0 && TREE_CODE(sym) != TYPE_DECL)
- || DECL_IGNORED_P(sym)
- || TREE_CODE(sym) != VAR_DECL
- || DECL_EXTERNAL(sym)
- || !rtx_equal_p(DECL_RTL(sym), orig)
- )
- continue;
-
- DECL_RTL(sym) = replacement;
- }
-
- replace_symbols_in_block(BLOCK_SUBBLOCKS(block), orig, replacement);
- }
-}
-
-void
-thumb_reorg(rtx first)
-{
- rtx insn;
- for (insn = first; insn; insn = NEXT_INSN(insn))
- {
- if (broken_move(insn))
- {
- /* This is a broken move instruction, scan ahead looking for
- a barrier to stick the constant table behind */
- rtx scan;
- rtx barrier = find_barrier(insn);
-
- /* Now find all the moves between the points and modify them */
- for (scan = insn; scan != barrier; scan = NEXT_INSN(scan))
- {
- if (broken_move(scan))
- {
- /* This is a broken move instruction, add it to the pool */
- rtx pat = PATTERN(scan);
- rtx src = SET_SRC(pat);
- rtx dst = SET_DEST(pat);
- enum machine_mode mode = GET_MODE(dst);
- HOST_WIDE_INT offset;
- rtx newinsn;
- rtx newsrc;
-
- /* If this is an HImode constant load, convert it into
- an SImode constant load. Since the register is always
- 32 bits this is safe. We have to do this, since the
- load pc-relative instruction only does a 32-bit load. */
- if (mode == HImode)
- {
- mode = SImode;
- if (GET_CODE(dst) != REG)
- abort();
- PUT_MODE(dst, SImode);
- }
-
- offset = add_constant(src, mode);
- newsrc = gen_rtx(MEM, mode,
- plus_constant(gen_rtx(LABEL_REF,
- VOIDmode,
- pool_vector_label),
- offset));
-
- /* Build a jump insn wrapper around the move instead
- of an ordinary insn, because we want to have room for
- the target label rtx in fld[7], which an ordinary
- insn doesn't have. */
- newinsn = emit_jump_insn_after(gen_rtx(SET, VOIDmode,
- dst, newsrc), scan);
- JUMP_LABEL(newinsn) = pool_vector_label;
-
- /* But it's still an ordinary insn */
- PUT_CODE(newinsn, INSN);
-
- /* If debugging information is going to be emitted
- then we must make sure that any refences to
- symbols which are removed by the above code are
- also removed in the descriptions of the
- function's variables. Failure to do this means
- that the debugging information emitted could
- refer to symbols which are not emited by
- output_constant_pool() because
- mark_constant_pool() never sees them as being
- used. */
-
-
- /* These are the tests used in
- output_constant_pool() to decide if the constant
- pool will be marked. Only necessary if debugging
- info is being emitted. Only necessary for
- references to memory whose address is given by a
- symbol. */
-
- if (optimize > 0
- && flag_expensive_optimizations
- && write_symbols != NO_DEBUG
- && GET_CODE(src) == MEM
- && GET_CODE(XEXP(src, 0)) == SYMBOL_REF)
- replace_symbols_in_block
- (DECL_INITIAL(current_function_decl), src, newsrc);
-
- /* Kill old insn */
- delete_insn(scan);
- scan = newinsn;
- }
- }
- dump_table(barrier);
- }
- }
-}
-
-/* Routines for generating rtl */
-
-void
-thumb_expand_movstrqi(rtx *operands)
-{
- rtx out = copy_to_mode_reg(SImode, XEXP(operands[0], 0));
- rtx in = copy_to_mode_reg(SImode, XEXP(operands[1], 0));
- HOST_WIDE_INT len = INTVAL(operands[2]);
- HOST_WIDE_INT offset = 0;
-
- while (len >= 12)
- {
- emit_insn(gen_movmem12b(out, in));
- len -= 12;
- }
- if (len >= 8)
- {
- emit_insn(gen_movmem8b(out, in));
- len -= 8;
- }
- if (len >= 4)
- {
- rtx reg = gen_reg_rtx(SImode);
- emit_insn(gen_movsi(reg, gen_rtx(MEM, SImode, in)));
- emit_insn(gen_movsi(gen_rtx(MEM, SImode, out), reg));
- len -= 4;
- offset += 4;
- }
- if (len >= 2)
- {
- rtx reg = gen_reg_rtx(HImode);
- emit_insn(gen_movhi(reg, gen_rtx(MEM, HImode,
- plus_constant(in, offset))));
- emit_insn(gen_movhi(gen_rtx(MEM, HImode, plus_constant(out, offset)),
- reg));
- len -= 2;
- offset += 2;
- }
- if (len)
- {
- rtx reg = gen_reg_rtx(QImode);
- emit_insn(gen_movqi(reg, gen_rtx(MEM, QImode,
- plus_constant(in, offset))));
- emit_insn(gen_movqi(gen_rtx(MEM, QImode, plus_constant(out, offset)),
- reg));
- }
-}
-
-/* Routines for reloading */
-
-void
-thumb_reload_out_si(rtx operands)
-{
- abort();
-}
-
-static int
-arm_naked_function_p(tree func)
-{
- tree a;
-
- if (TREE_CODE(func) != FUNCTION_DECL)
- abort();
-
- a = lookup_attribute("naked", DECL_MACHINE_ATTRIBUTES(func));
- return a != NULL_TREE;
-}
-
-/* Routines for emitting code */
-
-void
-final_prescan_insn(rtx insn)
-{
- extern int *insn_addresses;
-
- if (flag_print_asm_name)
- fprintf(asm_out_file, "%s 0x%04x\n", ASM_COMMENT_START,
- insn_addresses[INSN_UID(insn)]);
-}
-
-
-static void thumb_pushpop ( FILE *, int, int ); /* Forward declaration. */
-
-static inline int
-number_of_first_bit_set(int mask)
-{
- int bit;
-
- for (bit = 0;
- (mask & (1 << bit)) == 0;
- ++bit)
- continue;
-
- return bit;
-}
-
-#define ARG_1_REGISTER 0
-#define ARG_2_REGISTER 1
-#define ARG_3_REGISTER 2
-#define ARG_4_REGISTER 3
-#define WORK_REGISTER 7
-#define FRAME_POINTER 11
-#define IP_REGISTER 12
-#define STACK_POINTER STACK_POINTER_REGNUM
-#define LINK_REGISTER 14
-#define PROGRAM_COUNTER 15
-
-/* Generate code to return from a thumb function.
- If 'reg_containing_return_addr' is -1, then the return address is
- actually on the stack, at the stack pointer. */
-static void
-thumb_exit(FILE *f, int reg_containing_return_addr)
-{
- int reg_available_for_popping;
- int mode;
- int size;
- int restore_a4 = FALSE;
-
- if (reg_containing_return_addr != -1)
- {
- /* If the return address is in a register,
- then just emit the BX instruction and return. */
- asm_fprintf(f, "\tbx\t%s\n", reg_names[reg_containing_return_addr]);
- return;
- }
-
- if (!TARGET_THUMB_INTERWORK)
- {
- /* If we are not supporting interworking,
- then just pop the return address straight into the PC. */
- asm_fprintf(f, "\tpop\t{pc}\n" );
- return;
- }
-
- /* If we can deduce the registers used from the function's return value.
- This is more reliable that examining regs_ever_live[] because that
- will be set if the register is ever used in the function, not just if
- the register is used to hold a return value. */
-
- if (current_function_return_rtx != 0)
- mode = GET_MODE(current_function_return_rtx);
- else
- mode = DECL_MODE(DECL_RESULT(current_function_decl));
-
- size = GET_MODE_SIZE(mode);
-
- if (size == 0)
- {
- /* In a void function we can use any argument register.
- In a function that returns a structure on the stack
- we can use the second and third argument registers. */
- if (mode == VOIDmode)
- reg_available_for_popping = ARG_1_REGISTER;
- else
- reg_available_for_popping = ARG_2_REGISTER;
- }
- else if (size <= 4)
- {
- reg_available_for_popping = ARG_2_REGISTER;
- }
- else if (size <= 8)
- {
- reg_available_for_popping = ARG_3_REGISTER;
- }
- else
- {
- reg_available_for_popping = ARG_4_REGISTER;
-
- if (size > 12)
- {
- /* Register a4 is being used to hold part of the return value,
- but we have dire need of a free, low register. */
- restore_a4 = TRUE;
-
- asm_fprintf(f, "\tmov\t%s, %s\n",
- reg_names[IP_REGISTER], reg_names[ARG_4_REGISTER]);
- }
- }
-
- /* Pop the return address. */
- thumb_pushpop(f, (1 << reg_available_for_popping), FALSE);
-
- reg_containing_return_addr = reg_available_for_popping;
-
- /* If necessary restore the a4 register. */
- if (restore_a4)
- {
- asm_fprintf(f, "\tmov\t%s, %s\n",
- reg_names[LINK_REGISTER], reg_names[ARG_4_REGISTER]);
-
- reg_containing_return_addr = LINK_REGISTER;
-
- asm_fprintf(f, "\tmov\t%s, %s\n",
- reg_names[ARG_4_REGISTER], reg_names[IP_REGISTER]);
- }
-
- /* Return to caller. */
- asm_fprintf(f, "\tbx\t%s\n", reg_names[reg_containing_return_addr]);
-}
-
-/* Emit code to push or pop registers to or from the stack. */
-static void
-thumb_pushpop(FILE *f, int mask, int push)
-{
- int regno;
- int lo_mask = mask & 0xFF;
-
- if (lo_mask == 0 && !push && (mask & (1 << 15)))
- {
- /* Special case. Do not generate a POP PC statement here, do it in
- thumb_exit() */
-
- thumb_exit(f, -1);
- return;
- }
-
- asm_fprintf(f, "\t%s\t{", push ? "push" : "pop");
-
- /* Look at the low registers first. */
-
- for (regno = 0; regno < 8; regno++, lo_mask >>= 1)
- {
- if (lo_mask & 1)
- {
- asm_fprintf(f, reg_names[regno]);
-
- if ((lo_mask & ~1) != 0)
- asm_fprintf(f, ", ");
- }
- }
-
- if (push && (mask & (1 << 14)))
- {
- /* Catch pushing the LR. */
-
- if (mask & 0xFF)
- asm_fprintf(f, ", ");
-
- asm_fprintf(f, reg_names[14]);
- }
- else if (!push && (mask & (1 << 15)))
- {
- /* Catch popping the PC. */
-
- if (TARGET_THUMB_INTERWORK)
- {
- /* The PC is never popped directly, instead
- it is popped into r0-r3 and then BX is used. */
-
- asm_fprintf(f, "}\n");
-
- thumb_exit(f, -1);
-
- return;
- }
- else
- {
- if (mask & 0xFF)
- asm_fprintf(f, ", ");
-
- asm_fprintf(f, reg_names[15]);
- }
- }
-
- asm_fprintf(f, "}\n");
-}
-
-/* Returns non-zero if the current function contains a far jump */
-
-int
-far_jump_used_p()
-{
- rtx insn;
-
- if (current_function_has_far_jump)
- return 1;
-
- for (insn = get_insns(); insn; insn = NEXT_INSN(insn))
- {
- if (GET_CODE(insn) == JUMP_INSN
- /* Ignore tablejump patterns. */
- && GET_CODE(PATTERN(insn)) != ADDR_VEC
- && GET_CODE(PATTERN(insn)) != ADDR_DIFF_VEC
- && get_attr_far_jump(insn) == FAR_JUMP_YES)
- {
- current_function_has_far_jump = 1;
- return 1;
- }
- }
-
- return 0;
-}
-
-static int return_used_this_function = 0;
-
-void
-thumb_function_prologue(FILE *f, int frame_size)
-{
- int amount = frame_size + current_function_outgoing_args_size;
- int live_regs_mask = 0;
- int high_regs_pushed = 0;
- int store_arg_regs = 0;
- int regno;
-
- if (arm_naked_function_p(current_function_decl))
- return;
-
- if (current_function_anonymous_args && current_function_pretend_args_size)
- store_arg_regs = 1;
-
- if (current_function_pretend_args_size)
- {
- if (store_arg_regs)
- {
- asm_fprintf(f, "\tpush\t{");
- for (regno = 4 - current_function_pretend_args_size / 4; regno < 4;
- regno++)
- asm_fprintf(f, "%s%s", reg_names[regno], regno == 3 ? "" : ", ");
- asm_fprintf(f, "}\n");
- }
- else
- asm_fprintf(f, "\tsub\t%Rsp, %Rsp, #%d\n",
- current_function_pretend_args_size);
- }
-
- for (regno = 0; regno < 8; regno++)
- if (regs_ever_live[regno] && !call_used_regs[regno])
- live_regs_mask |= 1 << regno;
-
- if (live_regs_mask || !leaf_function_p() || far_jump_used_p())
- live_regs_mask |= 1 << 14;
-
- if (live_regs_mask)
- thumb_pushpop(f, live_regs_mask, 1);
-
- for (regno = 8; regno < 13; regno++)
- {
- if (regs_ever_live[regno] && !call_used_regs[regno])
- high_regs_pushed++;
- }
-
- if (high_regs_pushed)
- {
- int pushable_regs = 0;
- int mask = live_regs_mask & 0xff;
- int next_hi_reg;
-
- for (next_hi_reg = 12; next_hi_reg > 7; next_hi_reg--)
- {
- if (regs_ever_live[next_hi_reg] && !call_used_regs[next_hi_reg])
- break;
- }
-
- pushable_regs = mask;
-
- if (pushable_regs == 0)
- {
- /* desperation time -- this probably will never happen */
- if (regs_ever_live[3] || !call_used_regs[3])
- asm_fprintf(f, "\tmov\t%s, %s\n", reg_names[12], reg_names[3]);
- mask = 1 << 3;
- }
-
- while (high_regs_pushed > 0)
- {
- for (regno = 7; regno >= 0; regno--)
- {
- if (mask & (1 << regno))
- {
- asm_fprintf(f, "\tmov\t%s, %s\n", reg_names[regno],
- reg_names[next_hi_reg]);
- high_regs_pushed--;
- if (high_regs_pushed)
- for (next_hi_reg--; next_hi_reg > 7; next_hi_reg--)
- {
- if (regs_ever_live[next_hi_reg]
- && !call_used_regs[next_hi_reg])
- break;
- }
- else
- {
- mask &= ~((1 << regno) - 1);
- break;
- }
- }
- }
- thumb_pushpop(f, mask, 1);
- }
-
- if (pushable_regs == 0 && (regs_ever_live[3] || !call_used_regs[3]))
- asm_fprintf(f, "\tmov\t%s, %s\n", reg_names[3], reg_names[12]);
- }
-}
-
-void
-thumb_expand_prologue()
-{
- HOST_WIDE_INT amount = (get_frame_size()
- + current_function_outgoing_args_size);
- int regno;
- int live_regs_mask;
-
- if (arm_naked_function_p(current_function_decl))
- return;
-
- if (amount)
- {
- live_regs_mask = 0;
- for (regno = 0; regno < 8; regno++)
- if (regs_ever_live[regno] && !call_used_regs[regno])
- live_regs_mask |= 1 << regno;
-
- if (amount < 512)
- emit_insn(gen_addsi3(stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT(-amount)));
- else
- {
- rtx reg, spare;
-
- if ((live_regs_mask & 0xff) == 0) /* Very unlikely */
- emit_insn(gen_movsi(spare = gen_rtx(REG, SImode, 12),
- reg = gen_rtx(REG, SImode, 4)));
- else
- {
- for (regno = 0; regno < 8; regno++)
- if (live_regs_mask & (1 << regno))
- break;
- reg = gen_rtx(REG, SImode, regno);
- }
-
- emit_insn(gen_movsi(reg, GEN_INT(-amount)));
- emit_insn(gen_addsi3(stack_pointer_rtx, stack_pointer_rtx, reg));
- if ((live_regs_mask & 0xff) == 0)
- emit_insn(gen_movsi(reg, spare));
- }
- }
-
- if (frame_pointer_needed)
- {
- if (current_function_outgoing_args_size)
- {
- rtx offset = GEN_INT(current_function_outgoing_args_size);
-
- if (current_function_outgoing_args_size < 1024)
- emit_insn(gen_addsi3(frame_pointer_rtx, stack_pointer_rtx,
- offset));
- else
- {
- emit_insn(gen_movsi(frame_pointer_rtx, offset));
- emit_insn(gen_addsi3(frame_pointer_rtx, frame_pointer_rtx,
- stack_pointer_rtx));
- }
- }
- else
- emit_insn(gen_movsi(frame_pointer_rtx, stack_pointer_rtx));
- }
-
- /* if (profile_flag || profile_block_flag) */
- emit_insn(gen_blockage());
-}
-
-void
-thumb_expand_epilogue()
-{
- HOST_WIDE_INT amount = (get_frame_size()
- + current_function_outgoing_args_size);
- int regno;
-
- if (arm_naked_function_p(current_function_decl))
- return;
-
- if (amount)
- {
- if (amount < 512)
- emit_insn(gen_addsi3(stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT(amount)));
- else
- {
- rtx reg = gen_rtx(REG, SImode, 3); /* Always free in the epilogue */
-
- emit_insn(gen_movsi(reg, GEN_INT(amount)));
- emit_insn(gen_addsi3(stack_pointer_rtx, stack_pointer_rtx, reg));
- }
- /* if (profile_flag || profile_block_flag) */
- emit_insn(gen_blockage());
- }
-}
-
-void
-thumb_function_epilogue(FILE *f, int frame_size)
-{
- /* ??? Probably not safe to set this here, since it assumes that a
- function will be emitted as assembly immediately after we generate
- RTL for it. This does not happen for inline functions. */
- return_used_this_function = 0;
- current_function_has_far_jump = 0;
-#if 0 /* TODO : comment not really needed */
- fprintf(f, "%s THUMB Epilogue\n", ASM_COMMENT_START);
-#endif
-}
-
-/* The bits which aren't usefully expanded as rtl. */
-char *
-thumb_unexpanded_epilogue()
-{
- int regno;
- int live_regs_mask = 0;
- int high_regs_pushed = 0;
- int leaf_function = leaf_function_p();
- int had_to_push_lr;
-
- if (arm_naked_function_p(current_function_decl)
- || return_used_this_function)
- return "";
-
- for (regno = 0; regno < 8; regno++)
- if (regs_ever_live[regno] && !call_used_regs[regno])
- live_regs_mask |= 1 << regno;
-
- for (regno = 8; regno < 13; regno++)
- {
- if (regs_ever_live[regno] && !call_used_regs[regno])
- high_regs_pushed++;
- }
-
- /* The prolog may have pushed some high registers to use as
- work registers. eg the testuite file:
- gcc/testsuite/gcc/gcc.c-torture/execute/complex-2.c
- compiles to produce:
- push {r4, r5, r6, r7, lr}
- mov r7, r9
- mov r6, r8
- push {r6, r7}
- as part of the prolog. We have to undo that pushing here. */
-
- if (high_regs_pushed)
- {
- int mask = live_regs_mask;
- int next_hi_reg;
- int size;
- int mode;
-
- /* If we can deduce the registers used from the function's return value.
- This is more reliable that examining regs_ever_live[] because that
- will be set if the register is ever used in the function, not just if
- the register is used to hold a return value. */
-
- if (current_function_return_rtx != 0)
- {
- mode = GET_MODE(current_function_return_rtx);
- }
- else
- {
- mode = DECL_MODE(DECL_RESULT(current_function_decl));
- }
-
- size = GET_MODE_SIZE(mode);
-
- /* Unless we are returning a type of size > 12 register r3 is available. */
- if (size < 13)
- mask |= 1 << 3;
-
- if (mask == 0)
- {
- /* Oh dear! We have no low registers into which we can pop high registers! */
-
- fatal("No low registers available for popping high registers");
- }
-
- for (next_hi_reg = 8; next_hi_reg < 13; next_hi_reg++)
- if (regs_ever_live[next_hi_reg] && !call_used_regs[next_hi_reg])
- break;
-
- while (high_regs_pushed)
- {
- /* Find low register(s) into which the high register(s) can be popped. */
- for (regno = 0; regno < 8; regno++)
- {
- if (mask & (1 << regno))
- high_regs_pushed--;
- if (high_regs_pushed == 0)
- break;
- }
-
- mask &= (2 << regno) - 1; /* A noop if regno == 8 */
-
- /* Pop the values into the low register(s). */
- thumb_pushpop(asm_out_file, mask, 0);
-
- /* Move the value(s) into the high registers. */
- for (regno = 0; regno < 8; regno++)
- {
- if (mask & (1 << regno))
- {
- asm_fprintf(asm_out_file, "\tmov\t%s, %s\n",
- reg_names[next_hi_reg], reg_names[regno]);
- for (next_hi_reg++; next_hi_reg < 13; next_hi_reg++)
- if (regs_ever_live[next_hi_reg] &&
- !call_used_regs[next_hi_reg])
- break;
- }
- }
- }
- }
-
- had_to_push_lr = (live_regs_mask || !leaf_function || far_jump_used_p());
-
- if (current_function_pretend_args_size == 0)
- {
- if (had_to_push_lr)
- live_regs_mask |= 1 << PROGRAM_COUNTER;
-
- /* No argument registers were pushed, so just pop everything. */
-
- if (live_regs_mask)
- thumb_pushpop(asm_out_file, live_regs_mask, FALSE);
-
- /* We have either just popped the return address into the
- PC or it is was kept in LR for the entire function or
- it is still on the stack because we do not want to
- return by doing a pop {pc}. */
-
- if ((live_regs_mask & (1 << PROGRAM_COUNTER)) == 0)
- thumb_exit(asm_out_file, LINK_REGISTER);
- }
- else
- {
- /* Pop everything but the return address. */
- live_regs_mask &= ~(1 << PROGRAM_COUNTER);
-
- if (live_regs_mask)
- thumb_pushpop(asm_out_file, live_regs_mask, FALSE);
-
- if (had_to_push_lr)
- {
- /* Get the return address into a temporary register. */
- thumb_pushpop(asm_out_file, 1 << ARG_4_REGISTER, 0);
- }
-
- /* Remove the argument registers that were pushed onto the stack. */
- asm_fprintf(asm_out_file, "\tadd\t%s, %s, #%d\n",
- reg_names[STACK_POINTER],
- reg_names[STACK_POINTER],
- current_function_pretend_args_size);
-
- thumb_exit(asm_out_file, had_to_push_lr ? ARG_4_REGISTER : LINK_REGISTER);
- }
-
- return "";
-}
-
-/* Handle the case of a double word load into a low register from
- a computed memory address. The computed address may involve a
- register which is overwritten by the load. */
-
-char *
-thumb_load_double_from_address(rtx *operands)
-{
- rtx addr;
- rtx base;
- rtx offset;
- rtx arg1;
- rtx arg2;
-
- if (GET_CODE(operands[0]) != REG)
- fatal("thumb_load_double_from_address: destination is not a register");
-
- if (GET_CODE(operands[1]) != MEM)
- fatal("thumb_load_double_from_address: source is not a computed memory address");
-
- /* Get the memory address. */
-
- addr = XEXP(operands[1], 0);
-
- /* Work out how the memory address is computed. */
-
- switch (GET_CODE(addr))
- {
- case REG:
- operands[2] = gen_rtx(MEM, SImode, plus_constant(XEXP(operands[1], 0), 4));
-
- if (REGNO(operands[0]) == REGNO(addr))
- {
- output_asm_insn("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- }
- else
- {
- output_asm_insn("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- }
- break;
-
- case CONST:
- /* Compute <address> + 4 for the high order load. */
-
- operands[2] = gen_rtx(MEM, SImode, plus_constant(XEXP(operands[1], 0), 4));
-
- output_asm_insn("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- break;
-
- case PLUS:
- arg1 = XEXP(addr, 0);
- arg2 = XEXP(addr, 1);
-
- if (CONSTANT_P(arg1))
- base = arg2, offset = arg1;
- else
- base = arg1, offset = arg2;
-
- if (GET_CODE(base) != REG)
- fatal("thumb_load_double_from_address: base is not a register");
-
- /* Catch the case of <address> = <reg> + <reg> */
-
- if (GET_CODE(offset) == REG)
- {
- int reg_offset = REGNO(offset);
- int reg_base = REGNO(base);
- int reg_dest = REGNO(operands[0]);
-
- /* Add the base and offset registers together into the higher destination register. */
-
- fprintf(asm_out_file, "\tadd\t%s, %s, %s\t\t%s created by thumb_load_double_from_address",
- reg_names[ reg_dest + 1 ],
- reg_names[ reg_base ],
- reg_names[ reg_offset ],
- ASM_COMMENT_START);
-
- /* Load the lower destination register from the address in the higher destination register. */
-
- fprintf(asm_out_file, "\tldr\t%s,[%s, #0]\t\t%s created by thumb_load_double_from_address",
- reg_names[ reg_dest ],
- reg_names[ reg_dest + 1],
- ASM_COMMENT_START);
-
- /* Load the higher destination register from its own address plus 4. */
-
- fprintf(asm_out_file, "\tldr\t%s,[%s, #4]\t\t%s created by thumb_load_double_from_address",
- reg_names[ reg_dest + 1 ],
- reg_names[ reg_dest + 1 ],
- ASM_COMMENT_START);
- }
- else
- {
- /* Compute <address> + 4 for the high order load. */
-
- operands[2] = gen_rtx(MEM, SImode, plus_constant(XEXP(operands[1], 0), 4));
-
- /* If the computed address is held in the low order register
- then load the high order register first, otherwise always
- load the low order register first. */
-
- if (REGNO(operands[0]) == REGNO(base))
- {
- output_asm_insn("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- }
- else
- {
- output_asm_insn("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- }
- }
- break;
-
- case LABEL_REF:
- /* With no registers to worry about we can just load the value directly. */
- operands[2] = gen_rtx(MEM, SImode, plus_constant(XEXP(operands[1], 0), 4));
-
- output_asm_insn("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- break;
-
- default:
- debug_rtx(operands[1]);
- fatal("thumb_load_double_from_address: Unhandled address calculation");
- break;
- }
-
- return "";
-}
-
-char *
-output_move_mem_multiple(int n, rtx *operands)
-{
- rtx tmp;
-
- switch (n)
- {
- case 2:
- if (REGNO(operands[2]) > REGNO(operands[3]))
- {
- tmp = operands[2];
- operands[2] = operands[3];
- operands[3] = tmp;
- }
- output_asm_insn("ldmia\t%1!, {%2, %3}", operands);
- output_asm_insn("stmia\t%0!, {%2, %3}", operands);
- break;
-
- case 3:
- if (REGNO(operands[2]) > REGNO(operands[3]))
- {
- tmp = operands[2];
- operands[2] = operands[3];
- operands[3] = tmp;
- }
- if (REGNO(operands[3]) > REGNO(operands[4]))
- {
- tmp = operands[3];
- operands[3] = operands[4];
- operands[4] = tmp;
- }
- if (REGNO(operands[2]) > REGNO(operands[3]))
- {
- tmp = operands[2];
- operands[2] = operands[3];
- operands[3] = tmp;
- }
- output_asm_insn("ldmia\t%1!, {%2, %3, %4}", operands);
- output_asm_insn("stmia\t%0!, {%2, %3, %4}", operands);
- break;
-
- default:
- abort();
- }
-
- return "";
-}
-
-static char *conds[] =
-{
- "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
- "hi", "ls", "ge", "lt", "gt", "le"
-};
-
-static char *
-thumb_condition_code(rtx x, int invert)
-{
- int val;
-
- switch (GET_CODE(x))
- {
- case EQ: val = 0; break;
- case NE: val = 1; break;
- case GEU: val = 2; break;
- case LTU: val = 3; break;
- case GTU: val = 8; break;
- case LEU: val = 9; break;
- case GE: val = 10; break;
- case LT: val = 11; break;
- case GT: val = 12; break;
- case LE: val = 13; break;
- default:
- abort();
- }
-
- return conds[val ^ invert];
-}
-
-void
-thumb_print_operand(FILE *f, rtx x, int code)
-{
- if (code)
- {
- switch (code)
- {
- case '@':
- fputs(ASM_COMMENT_START, f);
- return;
-
- case 'D':
- if (x)
- fputs(thumb_condition_code(x, 1), f);
- return;
-
- case 'd':
- if (x)
- fputs(thumb_condition_code(x, 0), f);
- return;
-
- /* An explanation of the 'Q', 'R' and 'H' register operands:
-
- In a pair of registers containing a DI or DF value the 'Q'
- operand returns the register number of the register containing
- the least signficant part of the value. The 'R' operand returns
- the register number of the register containing the most
- significant part of the value.
-
- The 'H' operand returns the higher of the two register numbers.
- On a run where WORDS_BIG_ENDIAN is true the 'H' operand is the
- same as the 'Q' operand, since the most signficant part of the
- value is held in the lower number register. The reverse is true
- on systems where WORDS_BIG_ENDIAN is false.
-
- The purpose of these operands is to distinguish between cases
- where the endian-ness of the values is important (for example
- when they are added together), and cases where the endian-ness
- is irrelevant, but the order of register operations is important.
- For example when loading a value from memory into a register
- pair, the endian-ness does not matter. Provided that the value
- from the lower memory address is put into the lower numbered
- register, and the value from the higher address is put into the
- higher numbered register, the load will work regardless of whether
- the value being loaded is big-wordian or little-wordian. The
- order of the two register loads can matter however, if the address
- of the memory location is actually held in one of the registers
- being overwritten by the load. */
- case 'Q':
- if (REGNO(x) > 15)
- abort();
- fputs(reg_names[REGNO(x)], f);
- return;
-
- case 'R':
- if (REGNO(x) > 15)
- abort();
- fputs(reg_names[REGNO(x) + 1], f);
- return;
-
- case 'H':
- if (REGNO(x) > 15)
- abort();
- fputs(reg_names[REGNO(x) + 1], f);
- return;
-
- case 'c':
- /* We use 'c' operands with symbols for .vtinherit */
- if (GET_CODE(x) == SYMBOL_REF)
- output_addr_const(f, x);
- return;
-
- default:
- abort();
- }
- }
- if (GET_CODE(x) == REG)
- fputs(reg_names[REGNO(x)], f);
- else if (GET_CODE(x) == MEM)
- output_address(XEXP(x, 0));
- else if (GET_CODE(x) == CONST_INT)
- {
- fputc('#', f);
- output_addr_const(f, x);
- }
- else
- abort();
-}
-
-/* Decide whether a type should be returned in memory (true)
- or in a register (false). This is called by the macro
- RETURN_IN_MEMORY. */
-
-int
-thumb_return_in_memory(tree type)
-{
- if (!AGGREGATE_TYPE_P(type))
- {
- /* All simple types are returned in registers. */
-
- return 0;
- }
- else if (int_size_in_bytes(type) > 4)
- {
- /* All structures/unions bigger than one word are returned in memory. */
-
- return 1;
- }
- else if (TREE_CODE(type) == RECORD_TYPE)
- {
- tree field;
-
- /* For a struct the APCS says that we must return in a register if
- every addressable element has an offset of zero. For practical
- purposes this means that the structure can have at most one non-
- bit-field element and that this element must be the first one in
- the structure. */
-
- /* Find the first field, ignoring non FIELD_DECL things which will
- have been created by C++. */
- for (field = TYPE_FIELDS(type);
- field && TREE_CODE(field) != FIELD_DECL;
- field = TREE_CHAIN(field))
- continue;
-
- if (field == NULL)
- return 0; /* An empty structure. Allowed by an extension to ANSI C. */
-
- /* Now check the remaining fields, if any. */
- for (field = TREE_CHAIN(field); field; field = TREE_CHAIN(field))
- {
- if (TREE_CODE(field) != FIELD_DECL)
- continue;
-
- if (!DECL_BIT_FIELD_TYPE(field))
- return 1;
- }
-
- return 0;
- }
- else if (TREE_CODE(type) == UNION_TYPE)
- {
- tree field;
-
- /* Unions can be returned in registers if every element is
- integral, or can be returned in an integer register. */
-
- for (field = TYPE_FIELDS(type);
- field;
- field = TREE_CHAIN(field))
- {
- if (TREE_CODE(field) != FIELD_DECL)
- continue;
-
- if (RETURN_IN_MEMORY(TREE_TYPE(field)))
- return 1;
- }
-
- return 0;
- }
- /* XXX Not sure what should be done for other aggregates, so put them in
- memory. */
- return 1;
-}
-
-void
-thumb_override_options()
-{
- if (structure_size_string != NULL)
- {
- int size = strtol(structure_size_string, NULL, 0);
-
- if (size == 8 || size == 32)
- arm_structure_size_boundary = size;
- else
- warning("Structure size boundary can only be set to 8 or 32");
- }
-}
-
-/* Return nonzero if ATTR is a valid attribute for DECL.
- ATTRIBUTES are any existing attributes and ARGS are the arguments
- supplied with ATTR.
-
- Supported attributes:
-
- naked: don't output any prologue or epilogue code, the user is assumed
- to do the right thing.
- */
-int
-arm_valid_machine_decl_attribute(tree decl, tree attributes, tree attr, tree args)
-{
- if (args != NULL_TREE)
- return 0;
-
- if (is_attribute_p("naked", attr))
- return TREE_CODE(decl) == FUNCTION_DECL;
-
- return 0;
-}
-
-/* s_register_operand is the same as register_operand, but it doesn't accept
- (SUBREG (MEM)...).
-
- This function exists because at the time it was put in it led to better
- code. SUBREG(MEM) always needs a reload in the places where
- s_register_operand is used, and this seemed to lead to excessive
- reloading. */
-
-int
-s_register_operand(rtx op, enum machine_mode mode)
-{
- if (GET_MODE(op) != mode && mode != VOIDmode)
- return 0;
-
- if (GET_CODE(op) == SUBREG)
- op = SUBREG_REG(op);
-
- /* We don't consider registers whose class is NO_REGS
- to be a register operand. */
- /* XXX might have to check for lo regs only for thumb ??? */
- return (GET_CODE(op) == REG
- && (REGNO(op) >= FIRST_PSEUDO_REGISTER
- || REGNO_REG_CLASS(REGNO(op)) != NO_REGS));
-}
diff --git a/gcc/config/arm/thumb.h b/gcc/config/arm/thumb.h
deleted file mode 100755
index e5918a1..0000000
--- a/gcc/config/arm/thumb.h
+++ /dev/null
@@ -1,1137 +0,0 @@
-/* Definitions of target machine for GNU compiler, for ARM/Thumb.
- Copyright (C) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc.
- The basis of this contribution was generated by
- Richard Earnshaw, Advanced RISC Machines Ltd
-
-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. */
-
-/* ??? The files thumb.{c,h,md} are all seriously lacking comments. */
-
-/* ??? The files thumb.{c,h,md} need to be reviewed by an experienced
- gcc hacker in their entirety. */
-
-/* ??? The files thumb.{c,h,md} and tcoff.h are all separate from the arm
- files, which will lead to many maintenance problems. These files are
- likely missing all bug fixes made to the arm port since they diverged. */
-
-/* ??? Many patterns in the md file accept operands that will require a
- reload. These should be eliminated if possible by tightening the
- predicates and/or constraints. This will give faster/smaller code. */
-
-/* ??? There is no pattern for the TST instuction. Check for other unsupported
- instructions. */
-
-#define TARGET_VERSION fputs (" (ARM/THUMB:generic)", stderr);
-
-#define ARM_FLAG_THUMB 0x1000 /* same as in arm.h */
-#define THUMB_FLAG_CALLER_SUPER_INTERWORKING 0x80000
-
-/* Nonzero if all call instructions should be indirect. */
-#define ARM_FLAG_LONG_CALLS (0x10000) /* same as in arm.h */
-
-
-/* Run-time compilation parameters selecting different hardware/software subsets. */
-extern int target_flags;
-#define TARGET_DEFAULT 0 /* ARM_FLAG_THUMB */
-#define TARGET_THUMB_INTERWORK (target_flags & ARM_FLAG_THUMB)
-
-/* Set if calls via function pointers should assume that their
- destination is non-Thumb aware. */
-#define TARGET_CALLER_INTERWORKING \
- (target_flags & THUMB_FLAG_CALLER_SUPER_INTERWORKING)
-
-#define TARGET_LONG_CALLS (target_flags & ARM_FLAG_LONG_CALLS)
-
-/* SUBTARGET_SWITCHES is used to add flags on a per-config basis. */
-#ifndef SUBTARGET_SWITCHES
-#define SUBTARGET_SWITCHES
-#endif
-
-#define TARGET_SWITCHES \
-{ \
- {"thumb-interwork", ARM_FLAG_THUMB}, \
- {"no-thumb-interwork", -ARM_FLAG_THUMB}, \
- {"caller-super-interworking", THUMB_FLAG_CALLER_SUPER_INTERWORKING}, \
- {"no-caller-super-interworking", -THUMB_FLAG_CALLER_SUPER_INTERWORKING}, \
- {"long-calls", ARM_FLAG_LONG_CALLS, \
- "Generate all call instructions as indirect calls"}, \
- {"no-long-calls", -ARM_FLAG_LONG_CALLS, ""}, \
- SUBTARGET_SWITCHES \
- {"", TARGET_DEFAULT} \
-}
-
-#define TARGET_OPTIONS \
-{ \
- { "structure-size-boundary=", & structure_size_string }, \
-}
-
-#define REGISTER_PREFIX ""
-
-#define CAN_DEBUG_WITHOUT_FP 1
-
-#define ASM_APP_ON ""
-#define ASM_APP_OFF "\t.code\t16\n"
-
-/* Output a gap. In fact we fill it with nulls. */
-#define ASM_OUTPUT_SKIP(STREAM, NBYTES) \
- fprintf ((STREAM), "\t.space\t%u\n", (NBYTES))
-
-/* This is how to output an assembler line
- that says to advance the location counter
- to a multiple of 2**LOG bytes. */
-
-#ifdef OLD_ASM
-
-#define ASM_OUTPUT_ALIGN(STREAM,LOG) \
-{ \
- if ((LOG) > 0) \
- fprintf (STREAM, "\t.align\t%d\n", (LOG)); \
-}
-
-#else
-
-#define ASM_OUTPUT_ALIGN(STREAM,LOG) \
-{ \
- if ((LOG) > 0) \
- fprintf (STREAM, "\t.align\t%d, 0\n", (LOG)); \
-}
-
-#endif
-
-/* Output a common block */
-#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \
- (fprintf ((STREAM), "\t.comm\t"), \
- assemble_name ((STREAM), (NAME)), \
- fprintf((STREAM), ", %d\t%s %d\n", (ROUNDED), (ASM_COMMENT_START), (SIZE)))
-
-#define ASM_GENERATE_INTERNAL_LABEL(STRING,PREFIX,NUM) \
- sprintf ((STRING), "*%s%s%d", (LOCAL_LABEL_PREFIX), (PREFIX), (NUM))
-
-/* This is how to output an internal numbered label where
- PREFIX is the class of label and NUM is the number within the class. */
-#define ASM_OUTPUT_INTERNAL_LABEL(STREAM,PREFIX,NUM) \
- fprintf ((STREAM), "%s%s%d:\n", (LOCAL_LABEL_PREFIX), (PREFIX), (NUM))
-
-/* This is how to output a label which precedes a jumptable. Since
- instructions are 2 bytes, we need explicit alignment here. */
-
-#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,JUMPTABLE) \
- do { \
- ASM_OUTPUT_ALIGN (FILE, 2); \
- ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM); \
- } while (0)
-
-/* This says how to define a local common symbol (ie, not visible to
- linker). */
-#define ASM_OUTPUT_LOCAL(STREAM, NAME, SIZE, ROUNDED) \
- (fprintf((STREAM),"\n\t.lcomm\t"), \
- assemble_name((STREAM),(NAME)), \
- fprintf((STREAM),",%u\n",(SIZE)))
-
-/* Output a reference to a label. */
-#define ASM_OUTPUT_LABELREF(STREAM,NAME) \
- fprintf ((STREAM), "%s", (NAME))
-
-/* This is how to output an assembler line for a numeric constant byte. */
-#define ASM_OUTPUT_BYTE(STREAM,VALUE) \
- fprintf ((STREAM), "\t.byte\t0x%x\n", (VALUE))
-
-#define ASM_OUTPUT_INT(STREAM,VALUE) \
-{ \
- fprintf (STREAM, "\t.word\t"); \
- output_addr_const (STREAM, (VALUE)); \
- fprintf (STREAM, "\n"); \
-}
-
-#define ASM_OUTPUT_SHORT(STREAM,VALUE) \
-{ \
- fprintf (STREAM, "\t.short\t"); \
- output_addr_const (STREAM, (VALUE)); \
- fprintf (STREAM, "\n"); \
-}
-
-#define ASM_OUTPUT_CHAR(STREAM,VALUE) \
-{ \
- fprintf (STREAM, "\t.byte\t"); \
- output_addr_const (STREAM, (VALUE)); \
- fprintf (STREAM, "\n"); \
-}
-
-#define ASM_OUTPUT_DOUBLE(STREAM, VALUE) \
-do { char dstr[30]; \
- long l[2]; \
- REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
- REAL_VALUE_TO_DECIMAL (VALUE, "%.14g", dstr); \
- fprintf (STREAM, "\t.long 0x%lx, 0x%lx\t%s double %s\n", l[0], \
- l[1], ASM_COMMENT_START, dstr); \
- } while (0)
-
-#define ASM_OUTPUT_FLOAT(STREAM, VALUE) \
-do { char dstr[30]; \
- long l; \
- REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
- REAL_VALUE_TO_DECIMAL (VALUE, "%.7g", dstr); \
- fprintf (STREAM, "\t.word 0x%lx\t%s float %s\n", l, \
- ASM_COMMENT_START, dstr); \
- } while (0);
-
-/* Define results of standard character escape sequences. */
-#define TARGET_BELL 007
-#define TARGET_BS 010
-#define TARGET_TAB 011
-#define TARGET_NEWLINE 012
-#define TARGET_VT 013
-#define TARGET_FF 014
-#define TARGET_CR 015
-
-/* This is how to output a string. */
-#define ASM_OUTPUT_ASCII(STREAM, STRING, LEN) \
-do { \
- register int i, c, len = (LEN), cur_pos = 17; \
- register unsigned char *string = (unsigned char *)(STRING); \
- fprintf ((STREAM), "\t.ascii\t\""); \
- for (i = 0; i < len; i++) \
- { \
- register int c = string[i]; \
- \
- switch (c) \
- { \
- case '\"': \
- case '\\': \
- putc ('\\', (STREAM)); \
- putc (c, (STREAM)); \
- cur_pos += 2; \
- break; \
- \
- case TARGET_NEWLINE: \
- fputs ("\\n", (STREAM)); \
- if (i+1 < len \
- && (((c = string[i+1]) >= '\040' && c <= '~') \
- || c == TARGET_TAB)) \
- cur_pos = 32767; /* break right here */ \
- else \
- cur_pos += 2; \
- break; \
- \
- case TARGET_TAB: \
- fputs ("\\t", (STREAM)); \
- cur_pos += 2; \
- break; \
- \
- case TARGET_FF: \
- fputs ("\\f", (STREAM)); \
- cur_pos += 2; \
- break; \
- \
- case TARGET_BS: \
- fputs ("\\b", (STREAM)); \
- cur_pos += 2; \
- break; \
- \
- case TARGET_CR: \
- fputs ("\\r", (STREAM)); \
- cur_pos += 2; \
- break; \
- \
- default: \
- if (c >= ' ' && c < 0177) \
- { \
- putc (c, (STREAM)); \
- cur_pos++; \
- } \
- else \
- { \
- fprintf ((STREAM), "\\%03o", c); \
- cur_pos += 4; \
- } \
- } \
- \
- if (cur_pos > 72 && i+1 < len) \
- { \
- cur_pos = 17; \
- fprintf ((STREAM), "\"\n\t.ascii\t\""); \
- } \
- } \
- fprintf ((STREAM), "\"\n"); \
-} while (0)
-
-/* Output and Generation of Labels */
-#define ASM_OUTPUT_LABEL(STREAM,NAME) \
- (assemble_name ((STREAM), (NAME)), \
- fprintf ((STREAM), ":\n"))
-
-#define ASM_GLOBALIZE_LABEL(STREAM,NAME) \
- (fprintf ((STREAM), "\t.globl\t"), \
- assemble_name ((STREAM), (NAME)), \
- fputc ('\n', (STREAM)))
-
-/* Construct a private name. */
-#define ASM_FORMAT_PRIVATE_NAME(OUTVAR,NAME,NUMBER) \
- ((OUTVAR) = (char *) alloca (strlen (NAME) + 10), \
- sprintf ((OUTVAR), "%s.%d", (NAME), (NUMBER)))
-
-/* Switch to the text or data segment. */
-#define TEXT_SECTION_ASM_OP ".text"
-#define DATA_SECTION_ASM_OP ".data"
-#define BSS_SECTION_ASM_OP ".bss"
-
-/* The assembler's names for the registers. */
-#ifndef REGISTER_NAMES
-#define REGISTER_NAMES \
-{ \
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
- "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc", "ap" \
-}
-#endif
-
-#ifndef ADDITIONAL_REGISTER_NAMES
-#define ADDITIONAL_REGISTER_NAMES \
-{ \
- {"a1", 0}, \
- {"a2", 1}, \
- {"a3", 2}, \
- {"a4", 3}, \
- {"v1", 4}, \
- {"v2", 5}, \
- {"v3", 6}, \
- {"v4", 7}, \
- {"v5", 8}, \
- {"v6", 9}, \
- {"sb", 9}, \
- {"v7", 10}, \
- {"r10", 10}, /* sl */ \
- {"r11", 11}, /* fp */ \
- {"r12", 12}, /* ip */ \
- {"r13", 13}, /* sp */ \
- {"r14", 14}, /* lr */ \
- {"r15", 15} /* pc */ \
-}
-#endif
-
-/* The assembler's parentheses characters. */
-#define ASM_OPEN_PAREN "("
-#define ASM_CLOSE_PAREN ")"
-
-#ifndef ASM_COMMENT_START
-#define ASM_COMMENT_START "@"
-#endif
-
-/* Output an element of a dispatch table. */
-#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM,VALUE) \
- fprintf (STREAM, "\t.word\t%sL%d\n", (LOCAL_LABEL_PREFIX), (VALUE))
-
-#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM,BODY,VALUE,REL) \
- fprintf (STREAM, "\tb\t%sL%d\n", (LOCAL_LABEL_PREFIX), (VALUE))
-
-/* Storage Layout */
-
-#define FLOAT_WORDS_BIG_ENDIAN 1
-
-#define BITS_PER_UNIT 8
-#define BITS_PER_WORD 32
-
-#define UNITS_PER_WORD 4
-
-#define POINTER_SIZE 32
-
-#define PROMOTE_MODE(MODE,UNSIGNEDP,TYPE) \
-{ \
- if (GET_MODE_CLASS (MODE) == MODE_INT \
- && GET_MODE_SIZE (MODE) < 4) \
- { \
- (UNSIGNEDP) = 1; \
- (MODE) = SImode; \
- } \
-}
-
-#define PARM_BOUNDARY 32
-#define STACK_BOUNDARY 32
-
-#define FUNCTION_BOUNDARY 32
-#define BIGGEST_ALIGNMENT 32
-
-/* Make strings word-aligned so strcpy from constants will be faster. */
-#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
- (TREE_CODE (EXP) == STRING_CST \
- && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
-
-#define EMPTY_FIELD_BOUNDARY 32
-
-#define STRUCTURE_SIZE_BOUNDARY 32
-
-/* Used when parsing command line option -mstructure_size_boundary. */
-extern char * structure_size_string;
-
-#define STRICT_ALIGNMENT 1
-
-#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT
-
-
-/* Layout of Source Language Data Types */
-
-#define TARGET_BELL 007
-#define TARGET_BS 010
-#define TARGET_TAB 011
-#define TARGET_NEWLINE 012
-#define TARGET_VT 013
-#define TARGET_FF 014
-#define TARGET_CR 015
-
-
-/* Register Usage */
-
-/* Note there are 16 hard registers on the Thumb. We invent a 17th register
- which is assigned to ARG_POINTER_REGNUM, but this is later removed by
- elimination passes in the compiler. */
-#define FIRST_PSEUDO_REGISTER 17
-
-/* ??? This is questionable. */
-#define FIXED_REGISTERS \
-{ \
- 0,0,0,0, \
- 0,0,0,0, \
- 0,0,0,1, \
- 0,1,1,1,1 \
-}
-
-/* ??? This is questionable. */
-#define CALL_USED_REGISTERS \
-{ \
- 1,1,1,1, \
- 0,0,0,0, \
- 0,0,0,1, \
- 1,1,1,1,1 \
-}
-
-#define HARD_REGNO_NREGS(REGNO,MODE) \
- ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) \
- / UNITS_PER_WORD)
-
-/* ??? Probably should only allow DImode/DFmode in even numbered registers. */
-#define HARD_REGNO_MODE_OK(REGNO,MODE) ((GET_MODE_SIZE (MODE) > UNITS_PER_WORD) ? (REGNO < 7) : 1)
-
-#define MODES_TIEABLE_P(MODE1,MODE2) 1
-
-/* The NOARG_LO_REGS class is the set of LO_REGS that are not used for passing
- arguments to functions. These are the registers that are available for
- spilling during reload. The code in reload1.c:init_reload() will detect this
- class and place it into 'reload_address_base_reg_class'. */
-
-enum reg_class
-{
- NO_REGS,
- NONARG_LO_REGS,
- LO_REGS,
- STACK_REG,
- BASE_REGS,
- HI_REGS,
- ALL_REGS,
- LIM_REG_CLASSES
-};
-
-#define GENERAL_REGS ALL_REGS
-
-#define N_REG_CLASSES (int) LIM_REG_CLASSES
-
-#define REG_CLASS_NAMES \
-{ \
- "NO_REGS", \
- "NONARG_LO_REGS", \
- "LO_REGS", \
- "STACK_REG", \
- "BASE_REGS", \
- "HI_REGS", \
- "ALL_REGS" \
-}
-
-#define REG_CLASS_CONTENTS \
-{ \
- 0x00000, \
- 0x000f0, \
- 0x000ff, \
- 0x02000, \
- 0x020ff, \
- 0x0ff00, \
- 0x1ffff, \
-}
-
-#define REGNO_REG_CLASS(REGNO) \
- ((REGNO) == STACK_POINTER_REGNUM ? STACK_REG \
- : (REGNO) < 8 ? ((REGNO) < 4 ? LO_REGS \
- : NONARG_LO_REGS) \
- : HI_REGS)
-
-#define BASE_REG_CLASS BASE_REGS
-
-#define MODE_BASE_REG_CLASS(MODE) \
- ((MODE) != QImode && (MODE) != HImode \
- ? BASE_REGS : LO_REGS)
-
-#define INDEX_REG_CLASS LO_REGS
-
-/* When SMALL_REGISTER_CLASSES is nonzero, the compiler allows
- registers explicitly used in the rtl to be used as spill registers
- but prevents the compiler from extending the lifetime of these
- registers. */
-
-#define SMALL_REGISTER_CLASSES 1
-
-#define REG_CLASS_FROM_LETTER(C) \
- ((C) == 'l' ? LO_REGS \
- : (C) == 'h' ? HI_REGS \
- : (C) == 'b' ? BASE_REGS \
- : (C) == 'k' ? STACK_REG \
- : NO_REGS)
-
-#define REGNO_OK_FOR_BASE_P(REGNO) \
- ((REGNO) < 8 \
- || (REGNO) == STACK_POINTER_REGNUM \
- || (unsigned) reg_renumber[REGNO] < 8 \
- || (unsigned) reg_renumber[REGNO] == STACK_POINTER_REGNUM)
-
-#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) \
- ((REGNO) < 8 \
- || (unsigned) reg_renumber[REGNO] < 8 \
- || (GET_MODE_SIZE (MODE) >= 4 \
- && ((REGNO) == STACK_POINTER_REGNUM \
- || (unsigned) reg_renumber[REGNO] == STACK_POINTER_REGNUM)))
-
-#define REGNO_OK_FOR_INDEX_P(REGNO) \
- ((REGNO) < 8 \
- || (unsigned) reg_renumber[REGNO] < 8)
-
-/* ??? This looks suspiciously wrong. */
-/* We need to leave BASE_REGS reloads alone, in order to avoid caller_save
- lossage. Caller_saves requests a BASE_REGS reload (caller_save_spill_class)
- and then later we verify that one was allocated. If PREFERRED_RELOAD_CLASS
- says to allocate a LO_REGS spill instead, then this mismatch gives an
- abort. Alternatively, this could be fixed by modifying BASE_REG_CLASS
- to be LO_REGS instead of BASE_REGS. It is not clear what affect this
- change would have. */
-/* ??? This looks even more suspiciously wrong. PREFERRED_RELOAD_CLASS
- must always return a strict subset of the input class. Just blindly
- returning LO_REGS is safe only if the input class is a superset of LO_REGS,
- but there is no check for this. Added another exception for NONARG_LO_REGS
- because it is not a superset of LO_REGS. */
-/* ??? We now use NONARG_LO_REGS for caller_save_spill_class, so the
- comments about BASE_REGS are now obsolete. */
-#define PREFERRED_RELOAD_CLASS(X,CLASS) \
- ((CLASS) == BASE_REGS || (CLASS) == NONARG_LO_REGS ? (CLASS) \
- : LO_REGS)
-/*
- ((CONSTANT_P ((X)) && GET_CODE ((X)) != CONST_INT \
- && ! CONSTANT_POOL_ADDRESS_P((X))) ? NO_REGS \
- : (GET_CODE ((X)) == CONST_INT \
- && (HOST_WIDE_UINT) INTVAL ((X)) > 255) ? NO_REGS \
- : LO_REGS) */
-
-/* Must leave BASE_REGS and NONARG_LO_REGS reloads alone, see comment
- above. */
-#define SECONDARY_RELOAD_CLASS(CLASS,MODE,X) \
- ((CLASS) != LO_REGS && (CLASS) != BASE_REGS && (CLASS) != NONARG_LO_REGS \
- ? ((true_regnum (X) == -1 ? LO_REGS \
- : (true_regnum (X) + HARD_REGNO_NREGS (0, MODE) > 8) ? LO_REGS \
- : NO_REGS)) \
- : NO_REGS)
-
-#define CLASS_MAX_NREGS(CLASS,MODE) HARD_REGNO_NREGS(0,(MODE))
-
-int thumb_shiftable_const ();
-
-#define CONST_OK_FOR_LETTER_P(VAL,C) \
- ((C) == 'I' ? (HOST_WIDE_UINT) (VAL) < 256 \
- : (C) == 'J' ? (VAL) > -256 && (VAL) <= 0 \
- : (C) == 'K' ? thumb_shiftable_const (VAL) \
- : (C) == 'L' ? (VAL) > -8 && (VAL) < 8 \
- : (C) == 'M' ? ((HOST_WIDE_UINT) (VAL) < 1024 \
- && ((VAL) & 3) == 0) \
- : (C) == 'N' ? ((HOST_WIDE_UINT) (VAL) < 32) \
- : (C) == 'O' ? ((VAL) >= -508 && (VAL) <= 508) \
- : 0)
-
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VAL,C) 0
-
-#define EXTRA_CONSTRAINT(X,C) \
- ((C) == 'Q' ? (GET_CODE (X) == MEM \
- && GET_CODE (XEXP (X, 0)) == LABEL_REF) : 0)
-
-/* Stack Layout and Calling Conventions */
-
-#define STACK_GROWS_DOWNWARD 1
-
-/* #define FRAME_GROWS_DOWNWARD 1 */
-
-/* #define ARGS_GROW_DOWNWARD 1 */
-
-#define STARTING_FRAME_OFFSET 0
-
-#define FIRST_PARM_OFFSET(FNDECL) 0
-
-/* Registers that address the stack frame */
-
-#define STACK_POINTER_REGNUM 13 /* Defined by the TPCS. */
-
-#define FRAME_POINTER_REGNUM 7 /* TPCS defines this as 11 but it does not really mean it. */
-
-#define ARG_POINTER_REGNUM 16 /* A fake hard register that is eliminated later on. */
-
-#define STATIC_CHAIN_REGNUM 9
-
-#define FRAME_POINTER_REQUIRED 0
-
-#define ELIMINABLE_REGS \
-{{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
- {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
- {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}}
-
-/* On the Thumb we always want to perform the eliminations as we
- actually only have one real register pointing to the stashed
- variables: the stack pointer, and we never use the frame pointer. */
-#define CAN_ELIMINATE(FROM,TO) 1
-
-/* Note: This macro must match the code in thumb_function_prologue() in thumb.c. */
-#define INITIAL_ELIMINATION_OFFSET(FROM,TO,OFFSET) \
-{ \
- (OFFSET) = 0; \
- if ((FROM) == ARG_POINTER_REGNUM) \
- { \
- int count_regs = 0; \
- int regno; \
- (OFFSET) += get_frame_size (); \
- for (regno = 8; regno < 13; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- count_regs++; \
- if (count_regs) \
- (OFFSET) += 4 * count_regs; \
- count_regs = 0; \
- for (regno = 0; regno < 8; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- count_regs++; \
- if (count_regs || ! leaf_function_p () || far_jump_used_p()) \
- (OFFSET) += 4 * (count_regs + 1); \
- } \
- if ((TO) == STACK_POINTER_REGNUM) \
- (OFFSET) += current_function_outgoing_args_size; \
-}
-
-/* Passing Arguments on the stack */
-
-#define PROMOTE_PROTOTYPES 1
-
-#define ACCUMULATE_OUTGOING_ARGS 1
-
-#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0
-
-#define FUNCTION_ARG(CUM,MODE,TYPE,NAMED) \
- ((NAMED) ? ((CUM) >= 16 ? 0 : gen_rtx (REG, (MODE), (CUM) / 4)) \
- : 0)
-
-#define FUNCTION_ARG_PARTIAL_NREGS(CUM,MODE,TYPE,NAMED) \
- (((CUM) < 16 && (CUM) + (((MODE) == BLKmode) \
- ? int_size_in_bytes (TYPE) \
- : HARD_REGNO_NREGS (0, (MODE)) * 4) > 16) \
- ? 4 - (CUM) / 4 : 0)
-
-#define CUMULATIVE_ARGS int
-
-#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \
- ((CUM) = ((FNTYPE) && aggregate_value_p (TREE_TYPE (FNTYPE))) ? 4 : 0)
-
-#define FUNCTION_ARG_ADVANCE(CUM,MODE,TYPE,NAMED) \
- (CUM) += ((((MODE) == BLKmode) \
- ? int_size_in_bytes (TYPE) \
- : GET_MODE_SIZE (MODE)) + 3) & ~3
-
-#define FUNCTION_ARG_REGNO_P(REGNO) \
- ((REGNO) >=0 && (REGNO) <= 3)
-
-#define FUNCTION_VALUE(VALTYPE,FUNC) gen_rtx (REG, TYPE_MODE (VALTYPE), 0)
-
-#define LIBCALL_VALUE(MODE) gen_rtx (REG, (MODE), 0)
-
-#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == 0)
-
- /* How large values are returned */
-/* A C expression which can inhibit the returning of certain function values
- in registers, based on the type of value. */
-#define RETURN_IN_MEMORY(TYPE) thumb_return_in_memory (TYPE)
-
-/* Define DEFAULT_PCC_STRUCT_RETURN to 1 if all structure and union return
- values must be in memory. On the ARM, they need only do so if larger
- than a word, or if they contain elements offset from zero in the struct. */
-#define DEFAULT_PCC_STRUCT_RETURN 0
-
-
-#define STRUCT_VALUE_REGNUM 0
-
-#define FUNCTION_PROLOGUE(FILE,SIZE) thumb_function_prologue((FILE),(SIZE))
-
-#define FUNCTION_EPILOGUE(FILE,SIZE) thumb_function_epilogue((FILE),(SIZE))
-
-/* Implementing the Varargs Macros */
-
-#define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL) \
-{ \
- extern int current_function_anonymous_args; \
- current_function_anonymous_args = 1; \
- if ((CUM) < 16) \
- (PRETEND_SIZE) = 16 - (CUM); \
-}
-
-/* Trampolines for nested functions */
-
-/* Output assembler code for a block containing the constant parts of
- a trampoline, leaving space for the variable parts.
-
- On the Thumb we always switch into ARM mode to execute the trampoline.
- Why - because it is easier. This code will always be branched to via
- a BX instruction and since the compiler magically generates the address
- of the function the linker has no opportunity to ensure that the
- bottom bit is set. Thus the processor will be in ARM mode when it
- reaches this code. So we duplicate the ARM trampoline code and add
- a switch into Thumb mode as well.
-
- On the ARM, (if r8 is the static chain regnum, and remembering that
- referencing pc adds an offset of 8) the trampoline looks like:
- ldr r8, [pc, #0]
- ldr pc, [pc]
- .word static chain value
- .word function's address
- ??? FIXME: When the trampoline returns, r8 will be clobbered. */
-#define TRAMPOLINE_TEMPLATE(FILE) \
-{ \
- fprintf ((FILE), "\t.code 32\n"); \
- fprintf ((FILE), ".Ltrampoline_start:\n"); \
- fprintf ((FILE), "\tldr\t%s, [%spc, #8]\n", \
- reg_names[STATIC_CHAIN_REGNUM], REGISTER_PREFIX); \
- fprintf ((FILE), "\tldr\t%sip, [%spc, #8]\n", \
- REGISTER_PREFIX, REGISTER_PREFIX); \
- fprintf ((FILE), "\torr\t%sip, %sip, #1\n", \
- REGISTER_PREFIX, REGISTER_PREFIX); \
- fprintf ((FILE), "\tbx\t%sip\n", REGISTER_PREFIX); \
- fprintf ((FILE), "\t.word\t0\n"); \
- fprintf ((FILE), "\t.word\t0\n"); \
- fprintf ((FILE), "\t.code 16\n"); \
-}
-
-/* Length in units of the trampoline for entering a nested function. */
-#define TRAMPOLINE_SIZE 24
-
-/* Alignment required for a trampoline in units. */
-#define TRAMPOLINE_ALIGN 4
-
-#define INITIALIZE_TRAMPOLINE(ADDR,FNADDR,CHAIN) \
-{ \
- emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((ADDR), 16)), \
- (CHAIN)); \
- emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((ADDR), 20)), \
- (FNADDR)); \
-}
-
-
-/* Implicit Calls to Library Routines */
-
-#define TARGET_MEM_FUNCTIONS 1
-
-#define OVERRIDE_OPTIONS thumb_override_options ()
-
-
-/* Addressing Modes */
-
-#define HAVE_POST_INCREMENT 1
-
-#define CONSTANT_ADDRESS_P(X) \
- (GET_CODE (X) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (X))
-
-#define MAX_REGS_PER_ADDRESS 2
-
-#ifdef REG_OK_STRICT
-
-#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
-#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
-
-#define REG_MODE_OK_FOR_BASE_P(X,MODE) \
- REGNO_MODE_OK_FOR_BASE_P (REGNO (X), MODE)
-
-#else /* REG_OK_STRICT */
-
-#define REG_OK_FOR_BASE_P(X) \
- (REGNO (X) < 8 || REGNO (X) == STACK_POINTER_REGNUM \
- || (X) == arg_pointer_rtx \
- || REGNO (X) >= FIRST_PSEUDO_REGISTER)
-
-#define REG_MODE_OK_FOR_BASE_P(X,MODE) \
- (REGNO (X) < 8 \
- || REGNO (X) >= FIRST_PSEUDO_REGISTER \
- || (GET_MODE_SIZE (MODE) >= 4 \
- && (REGNO (X) == STACK_POINTER_REGNUM \
- || (X) == arg_pointer_rtx)))
-
-#define REG_OK_FOR_INDEX_P(X) \
- (REGNO (X) < 8 \
- || REGNO (X) >= FIRST_PSEUDO_REGISTER)
-
-#endif /* REG_OK_STRICT */
-
-/* In a REG+REG address, both must be INDEX registers. */
-#define REG_OK_FOR_INDEXED_BASE_P(X) REG_OK_FOR_INDEX_P(X)
-
-#define LEGITIMATE_OFFSET(MODE,VAL) \
-(GET_MODE_SIZE (MODE) == 1 ? ((HOST_WIDE_UINT) (VAL) < 32) \
- : GET_MODE_SIZE (MODE) == 2 ? ((HOST_WIDE_UINT) (VAL) < 64 \
- && ((VAL) & 1) == 0) \
- : ((VAL) >= 0 && ((VAL) + GET_MODE_SIZE (MODE)) <= 128 \
- && ((VAL) & 3) == 0))
-
-/* The AP may be eliminated to either the SP or the FP, so we use the
- least common denominator, e.g. SImode, and offsets from 0 to 64. */
-
-/* ??? Verify whether the above is the right approach. */
-
-/* ??? Also, the FP may be eliminated to the SP, so perhaps that
- needs special handling also. */
-
-/* ??? Look at how the mips16 port solves this problem. It probably uses
- better ways to solve some of these problems. */
-
-/* Although it is not incorrect, we don't accept QImode and HImode
- addresses based on the frame pointer or arg pointer until the reload pass starts.
- This is so that eliminating such addresses into stack based ones
- won't produce impossible code. */
-#define GO_IF_LEGITIMATE_ADDRESS(MODE,X,WIN) \
-{ \
- /* ??? Not clear if this is right. Experiment. */ \
- if (GET_MODE_SIZE (MODE) < 4 \
- && ! (reload_in_progress || reload_completed) \
- && (reg_mentioned_p (frame_pointer_rtx, X) \
- || reg_mentioned_p (arg_pointer_rtx, X) \
- || reg_mentioned_p (virtual_incoming_args_rtx, X) \
- || reg_mentioned_p (virtual_outgoing_args_rtx, X) \
- || reg_mentioned_p (virtual_stack_dynamic_rtx, X) \
- || reg_mentioned_p (virtual_stack_vars_rtx, X))) \
- ; \
- /* Accept any base register. SP only in SImode or larger. */ \
- else if (GET_CODE (X) == REG && REG_MODE_OK_FOR_BASE_P(X, MODE)) \
- goto WIN; \
- /* This is PC relative data before MACHINE_DEPENDENT_REORG runs. */ \
- else if (GET_MODE_SIZE (MODE) >= 4 && CONSTANT_P (X) \
- && CONSTANT_POOL_ADDRESS_P (X)) \
- goto WIN; \
- /* This is PC relative data after MACHINE_DEPENDENT_REORG runs. */ \
- else if (GET_MODE_SIZE (MODE) >= 4 && reload_completed \
- && (GET_CODE (X) == LABEL_REF \
- || (GET_CODE (X) == CONST \
- && GET_CODE (XEXP (X, 0)) == PLUS \
- && GET_CODE (XEXP (XEXP (X, 0), 0)) == LABEL_REF \
- && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT))) \
- goto WIN; \
- /* Post-inc indexing only supported for SImode and larger. */ \
- else if (GET_CODE (X) == POST_INC && GET_MODE_SIZE (MODE) >= 4 \
- && GET_CODE (XEXP (X, 0)) == REG \
- && REG_OK_FOR_INDEX_P (XEXP (X, 0))) \
- goto WIN; \
- else if (GET_CODE (X) == PLUS) \
- { \
- /* REG+REG address can be any two index registers. */ \
- /* ??? REG+REG addresses have been completely disabled before \
- reload completes, because we do not have enough available \
- reload registers. We only have 3 guaranteed reload registers \
- (NONARG_LO_REGS - the frame pointer), but we need at least 4 \
- to support REG+REG addresses. We have left them enabled after \
- reload completes, in the hope that reload_cse_regs and related \
- routines will be able to create them after the fact. It is \
- probably possible to support REG+REG addresses with additional \
- reload work, but I do not not have enough time to attempt such \
- a change at this time. */ \
- /* ??? Normally checking the mode here is wrong, since it isn't \
- impossible to use REG+REG with DFmode. However, the movdf \
- pattern requires offsettable addresses, and REG+REG is not \
- offsettable, so it must be rejected somehow. Trying to use \
- 'o' fails, because offsettable_address_p does a QImode check. \
- QImode is not valid for stack addresses, and has a smaller \
- range for non-stack bases, and this causes valid addresses \
- to be rejected. So we just eliminate REG+REG here by checking \
- the mode. */ \
- /* We also disallow FRAME+REG addressing since we know that FRAME \
- will be replaced with STACK, and SP relative addressing only \
- permits SP+OFFSET. */ \
- if (GET_MODE_SIZE (MODE) <= 4 \
- /* ??? See comment above. */ \
- && reload_completed \
- && GET_CODE (XEXP (X, 0)) == REG \
- && GET_CODE (XEXP (X, 1)) == REG \
- && XEXP (X, 0) != frame_pointer_rtx \
- && XEXP (X, 1) != frame_pointer_rtx \
- && XEXP (X, 0) != virtual_stack_vars_rtx \
- && XEXP (X, 1) != virtual_stack_vars_rtx \
- && REG_OK_FOR_INDEX_P (XEXP (X, 0)) \
- && REG_OK_FOR_INDEX_P (XEXP (X, 1))) \
- goto WIN; \
- /* REG+const has 5-7 bit offset for non-SP registers. */ \
- else if (GET_CODE (XEXP (X, 0)) == REG \
- && (REG_OK_FOR_INDEX_P (XEXP (X, 0)) \
- || XEXP (X, 0) == arg_pointer_rtx) \
- && GET_CODE (XEXP (X, 1)) == CONST_INT \
- && LEGITIMATE_OFFSET (MODE, INTVAL (XEXP (X, 1)))) \
- goto WIN; \
- /* REG+const has 10 bit offset for SP, but only SImode and \
- larger is supported. */ \
- /* ??? Should probably check for DI/DFmode overflow here \
- just like GO_IF_LEGITIMATE_OFFSET does. */ \
- else if (GET_CODE (XEXP (X, 0)) == REG \
- && REGNO (XEXP (X, 0)) == STACK_POINTER_REGNUM \
- && GET_MODE_SIZE (MODE) >= 4 \
- && GET_CODE (XEXP (X, 1)) == CONST_INT \
- && (HOST_WIDE_UINT) INTVAL (XEXP (X, 1)) < 1024 \
- && (INTVAL (XEXP (X, 1)) & 3) == 0) \
- goto WIN; \
- } \
-}
-
-/* ??? If an HImode FP+large_offset address is converted to an HImode
- SP+large_offset address, then reload won't know how to fix it. It sees
- only that SP isn't valid for HImode, and so reloads the SP into an index
- register, but the resulting address is still invalid because the offset
- is too big. We fix it here instead by reloading the entire address. */
-/* We could probably achieve better results by defining PROMOTE_MODE to help
- cope with the variances between the Thumb's signed and unsigned byte and
- halfword load instructions. */
-#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN) \
-{ \
- if (GET_CODE (X) == PLUS \
- && GET_MODE_SIZE (MODE) < 4 \
- && GET_CODE (XEXP (X, 0)) == REG \
- && XEXP (X, 0) == stack_pointer_rtx \
- && GET_CODE (XEXP (X, 1)) == CONST_INT \
- && ! LEGITIMATE_OFFSET (MODE, INTVAL (XEXP (X, 1)))) \
- { \
- rtx orig_X = X; \
- X = copy_rtx (X); \
- push_reload (orig_X, NULL_RTX, &X, NULL, \
- BASE_REG_CLASS, \
- Pmode, VOIDmode, 0, 0, OPNUM, TYPE); \
- goto WIN; \
- } \
-}
-
-#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL)
-
-#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN)
-
-#define LEGITIMATE_CONSTANT_P(X) \
- (GET_CODE (X) == CONST_INT \
- || GET_CODE (X) == CONST_DOUBLE \
- || CONSTANT_ADDRESS_P (X))
-
-
-/* Condition Code Status */
-
-#define NOTICE_UPDATE_CC(EXP,INSN) \
-{ \
- if (get_attr_conds ((INSN)) != CONDS_UNCHANGED) \
- CC_STATUS_INIT; \
-}
-
-
-/* Describing Relative Costs of Operations */
-
-#define SLOW_BYTE_ACCESS 0
-
-#define SLOW_UNALIGNED_ACCESS 1
-
-#define NO_FUNCTION_CSE 1
-
-#define NO_RECURSIVE_FUNCTION_CSE 1
-
-#define REGISTER_MOVE_COST(FROM,TO) \
- (((FROM) == HI_REGS || (TO) == HI_REGS) ? 4 : 2)
-
-#define MEMORY_MOVE_COST(M,CLASS,IN) \
- ((GET_MODE_SIZE(M) < 4 ? 8 : 2 * GET_MODE_SIZE(M)) * (CLASS == LO_REGS ? 1 : 2))
-
-/* This will allow better space optimization when compiling with -O */
-#define BRANCH_COST (optimize > 1 ? 1 : 0)
-
-#define RTX_COSTS(X,CODE,OUTER) \
- case MULT: \
- if (GET_CODE (XEXP (X, 1)) == CONST_INT) \
- { \
- int cycles = 0; \
- HOST_WIDE_UINT i = INTVAL (XEXP (X, 1)); \
- while (i) \
- { \
- i >>= 2; \
- cycles++; \
- } \
- return COSTS_N_INSNS (2) + cycles; \
- } \
- return COSTS_N_INSNS (1) + 16; \
- case ASHIFT: case ASHIFTRT: case LSHIFTRT: case ROTATERT: \
- case PLUS: case MINUS: case COMPARE: case NEG: case NOT: \
- return COSTS_N_INSNS (1); \
- case SET: \
- return (COSTS_N_INSNS (1) \
- + 4 * ((GET_CODE (SET_SRC (X)) == MEM) \
- + GET_CODE (SET_DEST (X)) == MEM))
-
-#define CONST_COSTS(X,CODE,OUTER) \
- case CONST_INT: \
- if ((OUTER) == SET) \
- { \
- if ((HOST_WIDE_UINT) INTVAL (X) < 256) \
- return 0; \
- if (thumb_shiftable_const (INTVAL (X))) \
- return COSTS_N_INSNS (2); \
- return COSTS_N_INSNS (3); \
- } \
- else if (OUTER == PLUS \
- && INTVAL (X) < 256 && INTVAL (X) > -256) \
- return 0; \
- else if (OUTER == COMPARE \
- && (HOST_WIDE_UINT) INTVAL (X) < 256) \
- return 0; \
- else if (OUTER == ASHIFT || OUTER == ASHIFTRT \
- || OUTER == LSHIFTRT) \
- return 0; \
- return COSTS_N_INSNS (2); \
- case CONST: \
- case CONST_DOUBLE: \
- case LABEL_REF: \
- case SYMBOL_REF: \
- return COSTS_N_INSNS(3);
-
-#define ADDRESS_COST(X) \
- ((GET_CODE (X) == REG \
- || (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == REG \
- && GET_CODE (XEXP (X, 1)) == CONST_INT)) \
- ? 1 : 2)
-
-
-/* Position Independent Code */
-
-#define PRINT_OPERAND(STREAM,X,CODE) \
- thumb_print_operand((STREAM), (X), (CODE))
-
-#define PRINT_OPERAND_ADDRESS(STREAM,X) \
-{ \
- if (GET_CODE ((X)) == REG) \
- fprintf ((STREAM), "[%s]", reg_names[REGNO ((X))]); \
- else if (GET_CODE ((X)) == POST_INC) \
- fprintf ((STREAM), "%s!", reg_names[REGNO (XEXP (X, 0))]); \
- else if (GET_CODE ((X)) == PLUS) \
- { \
- if (GET_CODE (XEXP ((X), 1)) == CONST_INT) \
- fprintf ((STREAM), "[%s, #%d]", \
- reg_names[REGNO (XEXP ((X), 0))], \
- (int) INTVAL (XEXP ((X), 1))); \
- else \
- fprintf ((STREAM), "[%s, %s]", \
- reg_names[REGNO (XEXP ((X), 0))], \
- reg_names[REGNO (XEXP ((X), 1))]); \
- } \
- else \
- output_addr_const ((STREAM), (X)); \
-}
-
-#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '@' || ((CODE) == '_'))
-
-#define ASM_OUTPUT_REG_PUSH(STREAM,REGNO) \
- asm_fprintf ((STREAM), "\tpush {%R%s}\n", reg_names[(REGNO)])
-
-#define ASM_OUTPUT_REG_POP(STREAM,REGNO) \
- fprintf ((STREAM), "\tpop {%R%s}\n", reg_names[(REGNO)])
-
-#define FINAL_PRESCAN_INSN(INSN,OPVEC,NOPERANDS) \
- final_prescan_insn((INSN))
-
-/* Controlling Debugging Information Format */
-#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
-
-/* Specific options for DBX Output */
-
-#define DBX_DEBUGGING_INFO 1
-
-#define DEFAULT_GDB_EXTENSIONS 1
-
-
-/* Cross Compilation and Floating Point */
-
-#define REAL_ARITHMETIC
-
-
-/* Miscellaneous Parameters */
-
-#define PREDICATE_CODES \
- {"thumb_cmp_operand", {SUBREG, REG, CONST_INT}},
-
-#define CASE_VECTOR_MODE Pmode
-
-#define WORD_REGISTER_OPERATIONS
-
-#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND
-
-#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
-
-#define EASY_DIV_EXPR TRUNC_DIV_EXPR
-
-#define MOVE_MAX 4
-
-#define TRULY_NOOP_TRUNCATION(OUTPREC,INPREC) 1
-
-#define STORE_FLAG_VALUE 1
-
-#define Pmode SImode
-
-#define FUNCTION_MODE SImode
-
-#define NO_DOLLAR_IN_LABEL 1
-
-#define HAVE_ATEXIT
-
-/* The literal pool needs to reside in the text area due to the
- limited PC addressing range: */
-#define MACHINE_DEPENDENT_REORG(INSN) thumb_reorg ((INSN))
-
-#include <stdio.h>
-
-enum machine_mode;
-
-struct rtx_def;
-typedef struct rtx_def *rtx;
-
-union tree_node;
-typedef union tree_node *tree;
-
-extern int thumb_cmp_operand(rtx, enum machine_mode);
-extern void thumb_reorg(rtx first);
-extern void thumb_expand_movstrqi(rtx *);
-extern void thumb_reload_out_si(rtx);
-extern void final_prescan_insn(rtx);
-extern int far_jump_used_p();
-extern void thumb_function_prologue(FILE *, int);
-extern void thumb_expand_prologue();
-extern void thumb_function_epilogue(FILE *, int);
-extern void thumb_expand_epilogue();
-extern char *thumb_unexpanded_epilogue();
-extern char *thumb_load_double_from_address();
-extern char *output_move_mem_multiple();
-extern void thumb_print_operand(FILE *, rtx, int);
-extern int thumb_return_in_memory(tree);
-extern void thumb_override_options();
-extern int arm_valid_machine_decl_attribute(tree, tree, tree, tree);
-extern int s_register_operand(rtx, enum machine_mode);
diff --git a/gcc/config/arm/thumb.md b/gcc/config/arm/thumb.md
deleted file mode 100755
index fe37c9c..0000000
--- a/gcc/config/arm/thumb.md
+++ /dev/null
@@ -1,1157 +0,0 @@
-;; thumb.md Machine description for ARM/Thumb processors
-;; Copyright (C) 1996, 1997, 1998, 2002 Free Software Foundation, Inc.
-;; The basis of this contribution was generated by
-;; Richard Earnshaw, Advanced RISC Machines Ltd
-
-;; 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.
-
-;; LENGTH of an instruction is 2 bytes
-(define_attr "length" "" (const_int 2))
-
-;; CONDS is set to UNCHANGED when an insn does not affect the condition codes
-;; Most insns change the condition codes
-(define_attr "conds" "changed,unchanged" (const_string "changed"))
-
-;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
-;; distant label.
-(define_attr "far_jump" "yes,no" (const_string "no"))
-
-;; Start with move insns
-
-(define_expand "movsi"
- [(set (match_operand:SI 0 "general_operand" "")
- (match_operand:SI 1 "general_operand" ""))]
- ""
- "
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (SImode, operands[1]);
- }
-")
-
-(define_insn "*movsi_insn"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l,m,*r,*h")
- (match_operand:SI 1 "general_operand" "l,I,J,K,>,l,mi,l,*h,*r"))]
- "register_operand (operands[0], SImode)
- || register_operand (operands[1], SImode)"
- "@
- add\\t%0, %1, #0
- mov\\t%0, %1
- #
- #
- ldmia\\t%1, {%0}
- stmia\\t%0, {%1}
- ldr\\t%0, %1
- str\\t%1, %0
- mov\\t%0, %1
- mov\\t%0, %1"
-[(set_attr "length" "2,2,4,4,2,2,2,2,2,2")])
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "const_int_operand" ""))]
- "thumb_shiftable_const (INTVAL (operands[1]))"
- [(set (match_dup 0) (match_dup 1))
- (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
- "
-{
- HOST_WIDE_UINT val = INTVAL (operands[1]);
- HOST_WIDE_UINT mask = 0xff;
- int i;
- for (i = 0; i < 25; i++)
- if ((val & (mask << i)) == val)
- break;
-
- if (i == 0)
- FAIL;
-
- operands[1] = GEN_INT (val >> i);
- operands[2] = GEN_INT (i);
-}")
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "const_int_operand" ""))]
- "INTVAL (operands[1]) < 0 && INTVAL (operands[1]) > -256"
- [(set (match_dup 0) (match_dup 1))
- (set (match_dup 0) (neg:SI (match_dup 0)))]
- "
- operands[1] = GEN_INT (- INTVAL (operands[1]));
-")
-
-(define_expand "movhi"
- [(set (match_operand:HI 0 "general_operand" "")
- (match_operand:HI 1 "general_operand" ""))]
- ""
- "
-{
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (HImode, operands[1]);
-
- /* ??? We shouldn't really get invalid addresses here, but this can
- happen if we are passed a SP (never OK for HImode/QImode) or virtual
- register (rejected by GO_IF_LEGITIMATE_ADDRESS for HImode/QImode)
- relative address. */
- /* ??? This should perhaps be fixed elsewhere, for instance, in
- fixup_stack_1, by checking for other kinds of invalid addresses,
- e.g. a bare reference to a virtual register. This may confuse the
- alpha though, which must handle this case differently. */
- if (GET_CODE (operands[0]) == MEM
- && ! memory_address_p (GET_MODE (operands[0]),
- XEXP (operands[0], 0)))
- {
- rtx temp = copy_to_reg (XEXP (operands[0], 0));
- operands[0] = change_address (operands[0], VOIDmode, temp);
- }
- if (GET_CODE (operands[1]) == MEM
- && ! memory_address_p (GET_MODE (operands[1]),
- XEXP (operands[1], 0)))
- {
- rtx temp = copy_to_reg (XEXP (operands[1], 0));
- operands[1] = change_address (operands[1], VOIDmode, temp);
- }
- }
- /* Handle loading a large integer during reload */
- else if (GET_CODE (operands[1]) == CONST_INT
- && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
- {
- /* Writing a constant to memory needs a scratch, which should
- be handled with SECONDARY_RELOADs. */
- if (GET_CODE (operands[0]) != REG)
- abort ();
-
- operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
- emit_insn (gen_movsi (operands[0], operands[1]));
- DONE;
- }
-}")
-
-(define_insn "*movhi_insn"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
- (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
- "register_operand (operands[0], HImode)
- || register_operand (operands[1], HImode)"
- "@
- add\\t%0, %1, #0
- ldrh\\t%0, %1
- strh\\t%1, %0
- mov\\t%0, %1
- mov\\t%0, %1
- mov\\t%0, %1")
-
-(define_expand "movqi"
- [(set (match_operand:QI 0 "general_operand" "")
- (match_operand:QI 1 "general_operand" ""))]
- ""
- "
-{
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (QImode, operands[1]);
-
- /* ??? We shouldn't really get invalid addresses here, but this can
- happen if we are passed a SP (never OK for HImode/QImode) or virtual
- register (rejected by GO_IF_LEGITIMATE_ADDRESS for HImode/QImode)
- relative address. */
- /* ??? This should perhaps be fixed elsewhere, for instance, in
- fixup_stack_1, by checking for other kinds of invalid addresses,
- e.g. a bare reference to a virtual register. This may confuse the
- alpha though, which must handle this case differently. */
- if (GET_CODE (operands[0]) == MEM
- && ! memory_address_p (GET_MODE (operands[0]),
- XEXP (operands[0], 0)))
- {
- rtx temp = copy_to_reg (XEXP (operands[0], 0));
- operands[0] = change_address (operands[0], VOIDmode, temp);
- }
- if (GET_CODE (operands[1]) == MEM
- && ! memory_address_p (GET_MODE (operands[1]),
- XEXP (operands[1], 0)))
- {
- rtx temp = copy_to_reg (XEXP (operands[1], 0));
- operands[1] = change_address (operands[1], VOIDmode, temp);
- }
- }
- /* Handle loading a large integer during reload */
- else if (GET_CODE (operands[1]) == CONST_INT
- && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
- {
- /* Writing a constant to memory needs a scratch, which should
- be handled with SECONDARY_RELOADs. */
- if (GET_CODE (operands[0]) != REG)
- abort ();
-
- operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
- emit_insn (gen_movsi (operands[0], operands[1]));
- DONE;
- }
-}")
-
-(define_insn "*movqi_insn"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
- (match_operand:QI 1 "general_operand" "l,m,l,*h,*r,I"))]
- "register_operand (operands[0], QImode)
- || register_operand (operands[1], QImode)"
- "@
- add\\t%0, %1, #0
- ldrb\\t%0, %1
- strb\\t%1, %0
- mov\\t%0, %1
- mov\\t%0, %1
- mov\\t%0, %1")
-
-(define_expand "movdi"
- [(set (match_operand:DI 0 "general_operand" "")
- (match_operand:DI 1 "general_operand" ""))]
- ""
- "
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (DImode, operands[1]);
- }
-")
-
-;;; ??? This should have alternatives for constants.
-;;; ??? This was originally identical to the movdf_insn pattern.
-;;; ??? The 'i' constraint looks funny, but it should always be replaced by
-;;; thumb_reorg with a memory reference.
-(define_insn "*movdi_insn"
- [(set (match_operand:DI 0 "general_operand" "=l,l,l,l,>,l,m,*r")
- (match_operand:DI 1 "general_operand" "l,I,J,>,l,mi,l,*r"))]
- "register_operand (operands[0], DImode)
- || register_operand (operands[1], DImode)"
- "*
-{
- switch (which_alternative)
- {
- case 0:
- if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
- return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
- return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
- case 1:
- return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
- case 2:
- operands[1] = GEN_INT (- INTVAL (operands[1]));
- return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
- case 3:
- return \"ldmia\\t%1, {%0, %H0}\";
- case 4:
- return \"stmia\\t%0, {%1, %H1}\";
- case 5:
- return thumb_load_double_from_address (operands);
- case 6:
- operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[0], 0), 4));
- output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
- return \"\";
- case 7:
- if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
- return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
- return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
- }
-}"[(set_attr "length" "4,4,6,2,2,6,4,4")])
-
-(define_expand "movdf"
- [(set (match_operand:DF 0 "general_operand" "")
- (match_operand:DF 1 "general_operand" ""))]
- ""
- "
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (DFmode, operands[1]);
- }
-")
-
-;;; ??? This should have alternatives for constants.
-;;; ??? This was originally identical to the movdi_insn pattern.
-;;; ??? The 'F' constraint looks funny, but it should always be replaced by
-;;; thumb_reorg with a memory reference.
-(define_insn "*movdf_insn"
- [(set (match_operand:DF 0 "general_operand" "=l,l,>,l,m,*r")
- (match_operand:DF 1 "general_operand" "l,>,l,mF,l,*r"))]
- "register_operand (operands[0], DFmode)
- || register_operand (operands[1], DFmode)"
- "*
- switch (which_alternative)
- {
- case 0:
- if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
- return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
- return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
- case 1:
- return \"ldmia\\t%1, {%0, %H0}\";
- case 2:
- return \"stmia\\t%0, {%1, %H1}\";
- case 3:
- return thumb_load_double_from_address (operands);
- case 4:
- operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[0], 0), 4));
- output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
- return \"\";
- case 5:
- if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
- return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
- return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
- }
-"[(set_attr "length" "4,2,2,6,4,4")])
-
-(define_expand "movsf"
- [(set (match_operand:SF 0 "general_operand" "")
- (match_operand:SF 1 "general_operand" ""))]
- ""
- "
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (SFmode, operands[1]);
- }
-")
-
-;;; ??? This should have alternatives for constants.
-(define_insn "*movsf_insn"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l,m,*r,*h")
- (match_operand:SF 1 "general_operand" "l,>,l,mF,l,*h,*r"))]
- "register_operand (operands[0], SFmode)
- || register_operand (operands[1], SFmode)"
- "@
- add\\t%0, %1, #0
- ldmia\\t%1, {%0}
- stmia\\t%0, {%1}
- ldr\\t%0, %1
- str\\t%1, %0
- mov\\t%0, %1
- mov\\t%0, %1")
-
-;; Widening move insns
-
-(define_expand "zero_extendhisi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
- ""
- "
- if (GET_CODE (operands[1]) != MEM)
- {
- rtx temp = gen_reg_rtx (SImode);
-
- operands[1] = force_reg (HImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_ashlsi3 (temp, operands[1], GEN_INT (16)));
- emit_insn (gen_lshrsi3 (operands[0], temp, GEN_INT (16)));
- DONE;
- }
-")
-
-(define_insn "*zero_extendhisi2_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
- ""
- "ldrh\\t%0, %1")
-
-(define_expand "zero_extendqisi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
- ""
- "
- if (GET_CODE (operands[1]) != MEM)
- {
- rtx temp = gen_reg_rtx (SImode);
-
- operands[1] = force_reg (QImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_ashlsi3 (temp, operands[1], GEN_INT (24)));
- emit_insn (gen_lshrsi3 (operands[0], temp, GEN_INT (24)));
- DONE;
- }
-")
-
-(define_insn "*zero_extendqisi2_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
- ""
- "ldrb\\t%0, %1")
-
-(define_expand "extendhisi2"
- [(parallel [(set (match_operand:SI 0 "s_register_operand" "")
- (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))
- (clobber (match_scratch:SI 2 ""))])]
- ""
- "
- if (GET_CODE (operands[1]) != MEM)
- {
- rtx temp = gen_reg_rtx (SImode);
-
- operands[1] = force_reg (HImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_ashlsi3 (temp, operands[1], GEN_INT (16)));
- emit_insn (gen_ashrsi3 (operands[0], temp, GEN_INT (16)));
- DONE;
- }
-")
-
-(define_insn "*extendhisi2_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
- (clobber (match_scratch:SI 2 "=&l"))]
- ""
- "*
-{
- rtx ops[4];
- /* This code used to try to use 'V', and fix the address only if it was
- offsettable, but this fails for e.g. REG+48 because 48 is outside the
- range of QImode offsets, and offsettable_address_p does a QImode
- address check. */
-
- if (GET_CODE (XEXP (operands[1], 0)) == PLUS)
- {
- ops[1] = XEXP (XEXP (operands[1], 0), 0);
- ops[2] = XEXP (XEXP (operands[1], 0), 1);
- }
- else
- {
- ops[1] = XEXP (operands[1], 0);
- ops[2] = const0_rtx;
- }
- if (GET_CODE (ops[2]) == REG)
- return \"ldrsh\\t%0, %1\";
-
- ops[0] = operands[0];
- ops[3] = operands[2];
- output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
- return \"\";
-}"
-[(set_attr "length" "4")])
-
-(define_expand "extendqisi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
- ""
- "
- if (GET_CODE (operands[1]) != MEM)
- {
- rtx temp = gen_reg_rtx (SImode);
-
- operands[1] = force_reg (QImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_ashlsi3 (temp, operands[1], GEN_INT (24)));
- emit_insn (gen_ashrsi3 (operands[0], temp, GEN_INT (24)));
- DONE;
- }
-")
-
-(define_insn "*extendqisi2_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=l,l")
- (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
- ""
- "*
-{
- rtx ops[3];
-
- if (which_alternative == 0)
- return \"ldrsb\\t%0, %1\";
- ops[0] = operands[0];
- if (GET_CODE (XEXP (operands[1], 0)) == PLUS)
- {
- ops[1] = XEXP (XEXP (operands[1], 0), 0);
- ops[2] = XEXP (XEXP (operands[1], 0), 1);
-
- if (GET_CODE (ops[1]) == REG && GET_CODE (ops[2]) == REG)
- output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
- else if (GET_CODE (ops[1]) == REG)
- {
- if (REGNO (ops[1]) == REGNO (operands[0]))
- output_asm_insn (\"ldrb\\t%0, [%1, %2]\;lsl\\t%0, %0, #24\;asr\\t%0, %0, #24\", ops);
- else
- output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
- }
- else
- {
- if (REGNO (ops[2]) == REGNO (operands[0]))
- output_asm_insn (\"ldrb\\t%0, [%2, %1]\;lsl\\t%0, %0, #24\;asr\\t%0, %0, #24\", ops);
- else
- output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
- }
- }
- else if (REGNO (operands[0]) == REGNO (XEXP (operands[1], 0)))
- {
- output_asm_insn (\"ldrb\\t%0, [%0, #0]\;lsl\\t%0, %0, #24\;asr\\t%0, %0, #24\", ops);
- }
- else
- {
- ops[1] = XEXP (operands[1], 0);
- ops[2] = const0_rtx;
- output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
- }
- return \"\";
-}"
-[(set_attr "length" "2,6")])
-
-;; We don't really have extzv, but defining this using shifts helps
-;; to reduce register pressure later on.
-
-(define_expand "extzv"
- [(set (match_dup 4)
- (ashift:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "const_int_operand" "")))
- (set (match_operand:SI 0 "register_operand" "")
- (lshiftrt:SI (match_dup 4)
- (match_operand:SI 3 "const_int_operand" "")))]
- ""
- "
-{
- HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
- HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
- operands[3] = GEN_INT (rshift);
- if (lshift == 0)
- {
- emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
- DONE;
- }
- operands[2] = GEN_INT (lshift);
- operands[4] = gen_reg_rtx (SImode);
-}
-")
-
-;; Block-move insns
-
-(define_expand "movstrqi"
- [(match_operand:BLK 0 "general_operand" "")
- (match_operand:BLK 1 "general_operand" "")
- (match_operand:SI 2 "" "")
- (match_operand:SI 3 "const_int_operand" "")]
- ""
- "
- if (INTVAL (operands[3]) != 4
- || GET_CODE (operands[2]) != CONST_INT
- || INTVAL (operands[2]) > 48)
- FAIL;
-
- thumb_expand_movstrqi (operands);
- DONE;
-")
-
-(define_insn "movmem12b"
- [(set (mem:SI (match_operand:SI 0 "register_operand" "+&l"))
- (mem:SI (match_operand:SI 1 "register_operand" "+&l")))
- (set (mem:SI (plus:SI (match_dup 0) (const_int 4)))
- (mem:SI (plus:SI (match_dup 1) (const_int 4))))
- (set (mem:SI (plus:SI (match_dup 0) (const_int 8)))
- (mem:SI (plus:SI (match_dup 1) (const_int 8))))
- (set (match_dup 0) (plus:SI (match_dup 0) (const_int 12)))
- (set (match_dup 1) (plus:SI (match_dup 1) (const_int 12)))
- (clobber (match_scratch:SI 2 "=&l"))
- (clobber (match_scratch:SI 3 "=&l"))
- (clobber (match_scratch:SI 4 "=&l"))]
- ""
- "* return output_move_mem_multiple (3, operands);"
-[(set_attr "length" "4")])
-
-(define_insn "movmem8b"
- [(set (mem:SI (match_operand:SI 0 "register_operand" "+&l"))
- (mem:SI (match_operand:SI 1 "register_operand" "+&l")))
- (set (mem:SI (plus:SI (match_dup 0) (const_int 4)))
- (mem:SI (plus:SI (match_dup 1) (const_int 4))))
- (set (match_dup 0) (plus:SI (match_dup 0) (const_int 8)))
- (set (match_dup 1) (plus:SI (match_dup 1) (const_int 8)))
- (clobber (match_scratch:SI 2 "=&l"))
- (clobber (match_scratch:SI 3 "=&l"))]
- ""
- "* return output_move_mem_multiple (2, operands);"
-[(set_attr "length" "4")])
-
-;; Arithmetic insns
-
-(define_insn "adddi3"
- [(set (match_operand:DI 0 "s_register_operand" "=l")
- (plus:DI (match_operand:DI 1 "s_register_operand" "%0")
- (match_operand:DI 2 "s_register_operand" "l")))]
- ""
- "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
-[(set_attr "conds" "changed")
- (set_attr "length" "8")])
-
-;; register group 'k' is a single register group containing only the stack
-;; register. Trying to reload it will always fail catastrophically,
-;; so never allow those alternatives to match if reloading is needed.
-(define_insn "addsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l,l,l,*r,*h,l,!k")
- (plus:SI (match_operand:SI 1 "s_register_operand" "%0,0,l,*0,*0,!k,!k")
- (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
- ""
- "*
- static char *asms[] =
-{
- \"add\\t%0, %0, %2\",
- \"sub\\t%0, %0, #%n2\",
- \"add\\t%0, %1, %2\",
- \"add\\t%0, %0, %2\",
- \"add\\t%0, %0, %2\",
- \"add\\t%0, %1, %2\",
- \"add\\t%0, %1, %2\"
-};
- if (which_alternative == 2 && GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) < 0)
- return \"sub\\t%0, %1, #%n2\";
- return asms[which_alternative];
-")
-
-; reloading and elimination of the frame pointer can sometimes cause this
-; optimization to be missed.
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=l")
- (match_operand:SI 1 "const_int_operand" "M"))
- (set (match_dup 0)
- (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "k")))]
- "REGNO (operands[2]) == STACK_POINTER_REGNUM
- && (HOST_WIDE_UINT) (INTVAL (operands[1])) < 1024
- && (INTVAL (operands[1]) & 3) == 0"
- "add\\t%0, %2, %1")
-
-(define_insn "subdi3"
- [(set (match_operand:DI 0 "s_register_operand" "=l")
- (minus:DI (match_operand:DI 1 "s_register_operand" "0")
- (match_operand:DI 2 "s_register_operand" "l")))]
- ""
- "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
-[(set_attr "conds" "changed")
- (set_attr "length" "8")])
-
-(define_insn "subsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (minus:SI (match_operand:SI 1 "s_register_operand" "l")
- (match_operand:SI 2 "s_register_operand" "l")))]
- ""
- "sub\\t%0, %1, %2")
-
-;; We must ensure that one input matches the output, and that the other input
-;; does not match the output. Using 0 satisfies the first, and using &
-;; satisfies the second. Unfortunately, this fails when operands 1 and 2
-;; are the same, because reload will make operand 0 match operand 1 without
-;; realizing that this conflicts with operand 2. We fix this by adding another
-;; alternative to match this case, and then `reload' it ourselves. This
-;; alternative must come first.
-(define_insn "mulsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=&l,&l,&l")
- (mult:SI (match_operand:SI 1 "s_register_operand" "%l,*h,0")
- (match_operand:SI 2 "s_register_operand" "l,l,l")))]
- ""
- "*
-{
- if (which_alternative < 2)
- return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
- else
- return \"mul\\t%0, %0, %2\";
-}"
- [(set_attr "length" "4,4,2")])
-
-(define_insn "negsi2"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (neg:SI (match_operand:SI 1 "s_register_operand" "l")))]
- ""
- "neg\\t%0, %1")
-
-;; Logical insns
-
-(define_expand "andsi3"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (and:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "nonmemory_operand" "")))]
- ""
- "
- if (GET_CODE (operands[2]) != CONST_INT)
- operands[2] = force_reg (SImode, operands[2]);
- else
- {
- int i;
- if (((HOST_WIDE_UINT) ~ INTVAL (operands[2])) < 256)
- {
- operands[2] = force_reg (SImode, GEN_INT (~INTVAL (operands[2])));
- emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
- DONE;
- }
-
- for (i = 9; i <= 31; i++)
- if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
- {
- emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
- const0_rtx));
- DONE;
- }
- else if ((((HOST_WIDE_INT) 1) << i) - 1 == ~ INTVAL (operands[2]))
- {
- rtx shift = GEN_INT (i);
- rtx reg = gen_reg_rtx (SImode);
- emit_insn (gen_lshrsi3 (reg, operands[1], shift));
- emit_insn (gen_ashlsi3 (operands[0], reg, shift));
- DONE;
- }
-
- operands[2] = force_reg (SImode, operands[2]);
- }
-")
-
-(define_insn "*andsi3_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (and:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "s_register_operand" "l")))]
- ""
- "and\\t%0, %0, %2")
-
-(define_insn "bicsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "l"))
- (match_operand:SI 2 "s_register_operand" "0")))]
- ""
- "bic\\t%0, %0, %1")
-
-(define_insn "iorsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (ior:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "s_register_operand" "l")))]
- ""
- "orr\\t%0, %0, %2")
-
-(define_insn "xorsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (xor:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "s_register_operand" "l")))]
- ""
- "eor\\t%0, %0, %2")
-
-(define_insn "one_cmplsi2"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (not:SI (match_operand:SI 1 "s_register_operand" "l")))]
- ""
- "mvn\\t%0, %1")
-
-;; Shift and rotation insns
-
-(define_insn "ashlsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l,l")
- (ashift:SI (match_operand:SI 1 "s_register_operand" "l,0")
- (match_operand:SI 2 "nonmemory_operand" "N,l")))]
- ""
- "@
- lsl\\t%0, %1, %2
- lsl\\t%0, %0, %2")
-
-(define_insn "ashrsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l,l")
- (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "l,0")
- (match_operand:SI 2 "nonmemory_operand" "N,l")))]
- ""
- "@
- asr\\t%0, %1, %2
- asr\\t%0, %0, %2")
-
-(define_insn "lshrsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l,l")
- (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "l,0")
- (match_operand:SI 2 "nonmemory_operand" "N,l")))]
- ""
- "@
- lsr\\t%0, %1, %2
- lsr\\t%0, %0, %2")
-
-(define_insn "rotrsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (rotatert:SI (match_operand:SI 1 "s_register_operand" "0")
- (match_operand:SI 2 "s_register_operand" "l")))]
- ""
- "ror\\t%0, %0, %2")
-
-;; Comparison insns
-
-(define_expand "cmpsi"
- [(set (cc0) (compare (match_operand:SI 0 "s_register_operand" "")
- (match_operand:SI 1 "nonmemory_operand" "")))]
- ""
- "
- if (GET_CODE (operands[1]) != REG && GET_CODE (operands[1]) != SUBREG)
- {
- if (GET_CODE (operands[1]) != CONST_INT
- || (HOST_WIDE_UINT) (INTVAL (operands[1])) >= 256)
- {
- if (GET_CODE (operands[1]) != CONST_INT
- || INTVAL (operands[1]) < -255
- || INTVAL (operands[1]) > 0)
- operands[1] = force_reg (SImode, operands[1]);
- else
- {
- operands[1] = force_reg (SImode,
- GEN_INT (- INTVAL (operands[1])));
- emit_insn (gen_cmnsi (operands[0], operands[1]));
- DONE;
- }
- }
- }
-")
-
-(define_insn "*cmpsi_insn"
- [(set (cc0) (compare (match_operand:SI 0 "s_register_operand" "l,*r,*h")
- (match_operand:SI 1 "thumb_cmp_operand" "lI,*h,*r")))]
- ""
- "@
- cmp\\t%0, %1
- cmp\\t%0, %1
- cmp\\t%0, %1")
-
-(define_insn "tstsi"
- [(set (cc0) (match_operand:SI 0 "s_register_operand" "l"))]
- ""
- "cmp\\t%0, #0")
-
-(define_insn "cmnsi"
- [(set (cc0) (compare (match_operand:SI 0 "s_register_operand" "l")
- (neg:SI (match_operand:SI 1 "s_register_operand" "l"))))]
- ""
- "cmn\\t%0, %1")
-
-;; Jump insns
-
-(define_insn "jump"
- [(set (pc) (label_ref (match_operand 0 "" "")))]
- ""
- "*
- if (get_attr_length (insn) == 2)
- return \"b\\t%l0\";
- return \"bl\\t%l0\\t%@ far jump\";
-"[(set (attr "far_jump")
- (if_then_else (eq_attr "length" "4")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
- (le (minus (match_dup 0) (pc)) (const_int 2044)))
- (const_int 2)
- (const_int 4)))])
-
-
-(define_expand "beq"
- [(set (pc) (if_then_else (eq (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bne"
- [(set (pc) (if_then_else (ne (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bge"
- [(set (pc) (if_then_else (ge (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "ble"
- [(set (pc) (if_then_else (le (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bgt"
- [(set (pc) (if_then_else (gt (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "blt"
- [(set (pc) (if_then_else (lt (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bgeu"
- [(set (pc) (if_then_else (geu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bleu"
- [(set (pc) (if_then_else (leu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bgtu"
- [(set (pc) (if_then_else (gtu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bltu"
- [(set (pc) (if_then_else (ltu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_insn "*cond_branch"
- [(set (pc) (if_then_else (match_operator 1 "comparison_operator"
- [(cc0) (const_int 0)])
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
- switch (get_attr_length (insn))
- {
- case 2: return \"b%d1\\t%l0\\t%@cond_branch\";
- case 4: return \"b%D1\\t.LCB%=\;b\\t%l0\\t%@long jump\\n.LCB%=:\";
- default: return \"b%D1\\t.LCB%=\;bl\\t%l0\\t%@far jump\\n.LCB%=:\";
- }
-"[(set (attr "far_jump")
- (if_then_else (eq_attr "length" "6")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (and (ge (minus (match_dup 0) (pc)) (const_int -252))
- (le (minus (match_dup 0) (pc)) (const_int 254)))
- (const_int 2)
- (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
- (le (minus (match_dup 0) (pc)) (const_int 2044)))
- (const_int 4)
- (const_int 6))))])
-
-(define_insn "*cond_branch_reversed"
- [(set (pc) (if_then_else (match_operator 1 "comparison_operator"
- [(cc0) (const_int 0)])
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "*
- switch (get_attr_length (insn))
- {
- case 2: return \"b%D1\\t%l0\\t%@cond_branch_reversed\";
- case 4: return \"b%d1\\t.LCBR%=\;b\\t%l0\\t%@long jump\\n.LCBR%=:\";
- default: return \"b%d1\\t.LCBR%=\;bl\\t%l0\\t%@far jump\\n.LCBR%=:\";
- }
- return \"\";
-"[(set (attr "far_jump")
- (if_then_else (eq_attr "length" "6")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (and (ge (minus (match_dup 0) (pc)) (const_int -252))
- (le (minus (match_dup 0) (pc)) (const_int 254)))
- (const_int 2)
- (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
- (le (minus (match_dup 0) (pc)) (const_int 2044)))
- (const_int 4)
- (const_int 6))))])
-
-(define_insn "indirect_jump"
- [(set (pc) (match_operand:SI 0 "s_register_operand" "l*r"))]
- ""
- "mov\\tpc, %0")
-
-(define_insn "tablejump"
- [(set (pc) (match_operand:SI 0 "s_register_operand" "l*r"))
- (use (label_ref (match_operand 1 "" "")))]
- ""
- "mov\\tpc, %0")
-
-;; Call insns
-
-(define_expand "call"
- [(call (match_operand:SI 0 "memory_operand" "")
- (match_operand 1 "" ""))]
- ""
- "
-{
- if (TARGET_LONG_CALLS && GET_CODE (XEXP (operands[0], 0)) != REG)
- XEXP (operands[0], 0) = force_reg (Pmode, XEXP (operands[0], 0));
-}")
-
-(define_insn "*call_indirect"
- [(call (mem:SI (match_operand:SI 0 "s_register_operand" "l*r"))
- (match_operand 1 "" ""))]
- "! TARGET_CALLER_INTERWORKING"
- "bl\\t_call_via_%0"
-[(set_attr "length" "4")])
-;; The non THUMB_INTERWORK, non TARGET_CALLER_INTERWORKING version
-;; used to be: "mov\\tlr,pc\;bx\\t%0", but the mov does not set
-;; the bottom bit of lr so that a function return (using bx)
-;; would switch back into ARM mode...
-
-(define_insn "*call_indirect_interwork"
- [(call (mem:SI (match_operand:SI 0 "s_register_operand" "l*r"))
- (match_operand 1 "" ""))]
- "TARGET_CALLER_INTERWORKING"
- "bl\\t_interwork_call_via_%0"
-[(set_attr "length" "4")])
-
-(define_expand "call_value"
- [(set (match_operand 0 "" "")
- (call (match_operand 1 "memory_operand" "")
- (match_operand 2 "" "")))]
- ""
- "
-{
- if (TARGET_LONG_CALLS && GET_CODE (XEXP (operands[1], 0)) != REG)
- XEXP (operands[1], 0) = force_reg (Pmode, XEXP (operands[1], 0));
-}")
-
-(define_insn "*call_value_indirect"
- [(set (match_operand 0 "" "=l")
- (call (mem:SI (match_operand:SI 1 "s_register_operand" "l*r"))
- (match_operand 2 "" "")))]
- "! TARGET_CALLER_INTERWORKING"
- "bl\\t_call_via_%1"
-[(set_attr "length" "4")])
-;; See comment for call_indirect pattern
-
-(define_insn "*call_value_indirect_interwork"
- [(set (match_operand 0 "" "=l")
- (call (mem:SI (match_operand:SI 1 "s_register_operand" "l*r"))
- (match_operand 2 "" "")))]
- "TARGET_CALLER_INTERWORKING"
- "bl\\t_interwork_call_via_%1"
-[(set_attr "length" "4")])
-
-
-(define_insn "*call_insn"
- [(call (mem:SI (match_operand:SI 0 "" "i"))
- (match_operand:SI 1 "" ""))]
- "! TARGET_LONG_CALLS && GET_CODE (operands[0]) == SYMBOL_REF"
- "bl\\t%a0"
-[(set_attr "length" "4")])
-
-(define_insn "*call_value_insn"
- [(set (match_operand 0 "s_register_operand" "=l")
- (call (mem:SI (match_operand 1 "" "i"))
- (match_operand 2 "" "")))]
- "! TARGET_LONG_CALLS && GET_CODE (operands[1]) == SYMBOL_REF"
- "bl\\t%a1"
-[(set_attr "length" "4")])
-
-;; Untyped call not required, since all funcs return in r0
-
-;; Miscellaneous patterns
-
-(define_insn "nop"
- [(clobber (const_int 0))]
- ""
- "mov\\tr8, r8")
-
-(define_insn "blockage"
- [(unspec_volatile [(const_int 0)] 0)]
- ""
- ""
- [(set_attr "length" "0")])
-
-(define_expand "prologue"
- [(const_int 0)]
- ""
- "
- thumb_expand_prologue ();
- DONE;
-")
-
-(define_expand "epilogue"
- [(unspec_volatile [(const_int 0)] 1)]
- ""
- "
- thumb_expand_epilogue ();
-")
-
-(define_insn "*epilogue_insns"
- [(unspec_volatile [(const_int 0)] 1)]
- ""
- "*
- return thumb_unexpanded_epilogue ();
-"
-[(set_attr "length" "42")])
-
-;; Special patterns for dealing with the constant pool
-
-(define_insn "consttable_4"
- [(unspec_volatile [(match_operand 0 "" "")] 2)]
- ""
- "*
-{
- switch (GET_MODE_CLASS (GET_MODE (operands[0])))
- {
- case MODE_FLOAT:
- {
- union real_extract u;
- memcpy((char *)&u, (char *)&CONST_DOUBLE_LOW(operands[0]), sizeof u);
- assemble_real (u.d, GET_MODE (operands[0]));
- break;
- }
- default:
- assemble_integer (operands[0], 4, 1);
- break;
- }
- return \"\";
-}"
-[(set_attr "length" "4")])
-
-(define_insn "consttable_8"
- [(unspec_volatile [(match_operand 0 "" "")] 3)]
- ""
- "*
-{
- switch (GET_MODE_CLASS (GET_MODE (operands[0])))
- {
- case MODE_FLOAT:
- {
- union real_extract u;
- memcpy((char *)&u, (char *)&CONST_DOUBLE_LOW(operands[0]), sizeof u);
- assemble_real (u.d, GET_MODE (operands[0]));
- break;
- }
- default:
- assemble_integer (operands[0], 8, 1);
- break;
- }
- return \"\";
-}"
-[(set_attr "length" "8")])
-
-(define_insn "consttable_end"
- [(unspec_volatile [(const_int 0)] 4)]
- ""
- "*
- /* Nothing to do (currently). */
- return \"\";
-")
-
-(define_insn "align_4"
- [(unspec_volatile [(const_int 0)] 5)]
- ""
- "*
- assemble_align (32);
- return \"\";
-")