aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.2.1/gcc/config/arm
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.2.1/gcc/config/arm')
-rw-r--r--gcc-4.2.1/gcc/config/arm/README-interworking742
-rw-r--r--gcc-4.2.1/gcc/config/arm/aof.h296
-rw-r--r--gcc-4.2.1/gcc/config/arm/aout.h301
-rw-r--r--gcc-4.2.1/gcc/config/arm/arm-cores.def117
-rw-r--r--gcc-4.2.1/gcc/config/arm/arm-generic.md152
-rw-r--r--gcc-4.2.1/gcc/config/arm/arm-libgcc2.c118
-rw-r--r--gcc-4.2.1/gcc/config/arm/arm-modes.def60
-rw-r--r--gcc-4.2.1/gcc/config/arm/arm-protos.h191
-rw-r--r--gcc-4.2.1/gcc/config/arm/arm-tune.md5
-rw-r--r--gcc-4.2.1/gcc/config/arm/arm.c15651
-rw-r--r--gcc-4.2.1/gcc/config/arm/arm.h2604
-rw-r--r--gcc-4.2.1/gcc/config/arm/arm.md10304
-rw-r--r--gcc-4.2.1/gcc/config/arm/arm.opt155
-rw-r--r--gcc-4.2.1/gcc/config/arm/arm1020e.md388
-rw-r--r--gcc-4.2.1/gcc/config/arm/arm1026ejs.md241
-rw-r--r--gcc-4.2.1/gcc/config/arm/arm1136jfs.md377
-rw-r--r--gcc-4.2.1/gcc/config/arm/arm926ejs.md188
-rw-r--r--gcc-4.2.1/gcc/config/arm/bpabi.S95
-rw-r--r--gcc-4.2.1/gcc/config/arm/bpabi.c61
-rw-r--r--gcc-4.2.1/gcc/config/arm/bpabi.h121
-rw-r--r--gcc-4.2.1/gcc/config/arm/cirrus.md458
-rw-r--r--gcc-4.2.1/gcc/config/arm/coff.h85
-rw-r--r--gcc-4.2.1/gcc/config/arm/constraints.md186
-rw-r--r--gcc-4.2.1/gcc/config/arm/crti.asm89
-rw-r--r--gcc-4.2.1/gcc/config/arm/crtn.asm84
-rw-r--r--gcc-4.2.1/gcc/config/arm/eabi.h134
-rw-r--r--gcc-4.2.1/gcc/config/arm/eabi.opt23
-rw-r--r--gcc-4.2.1/gcc/config/arm/ecos-elf.h28
-rw-r--r--gcc-4.2.1/gcc/config/arm/elf.h157
-rw-r--r--gcc-4.2.1/gcc/config/arm/fpa.md750
-rw-r--r--gcc-4.2.1/gcc/config/arm/freebsd.h68
-rwxr-xr-xgcc-4.2.1/gcc/config/arm/gentune.sh12
-rw-r--r--gcc-4.2.1/gcc/config/arm/ieee754-df.S1335
-rw-r--r--gcc-4.2.1/gcc/config/arm/ieee754-sf.S976
-rw-r--r--gcc-4.2.1/gcc/config/arm/iwmmxt.md1528
-rw-r--r--gcc-4.2.1/gcc/config/arm/kaos-arm.h24
-rw-r--r--gcc-4.2.1/gcc/config/arm/kaos-strongarm.h24
-rw-r--r--gcc-4.2.1/gcc/config/arm/lib1funcs.asm1392
-rw-r--r--gcc-4.2.1/gcc/config/arm/libgcc-bpabi.ver89
-rw-r--r--gcc-4.2.1/gcc/config/arm/libunwind.S127
-rw-r--r--gcc-4.2.1/gcc/config/arm/linux-eabi.h85
-rw-r--r--gcc-4.2.1/gcc/config/arm/linux-elf.h110
-rw-r--r--gcc-4.2.1/gcc/config/arm/linux-gas.h55
-rw-r--r--gcc-4.2.1/gcc/config/arm/mmintrin.h1257
-rw-r--r--gcc-4.2.1/gcc/config/arm/netbsd-elf.h158
-rw-r--r--gcc-4.2.1/gcc/config/arm/netbsd.h153
-rw-r--r--gcc-4.2.1/gcc/config/arm/pe.c269
-rw-r--r--gcc-4.2.1/gcc/config/arm/pe.h149
-rw-r--r--gcc-4.2.1/gcc/config/arm/pe.opt24
-rw-r--r--gcc-4.2.1/gcc/config/arm/pr-support.c381
-rw-r--r--gcc-4.2.1/gcc/config/arm/predicates.md458
-rw-r--r--gcc-4.2.1/gcc/config/arm/rtems-elf.h46
-rw-r--r--gcc-4.2.1/gcc/config/arm/semi.h76
-rw-r--r--gcc-4.2.1/gcc/config/arm/semiaof.h40
-rw-r--r--gcc-4.2.1/gcc/config/arm/strongarm-coff.h28
-rw-r--r--gcc-4.2.1/gcc/config/arm/strongarm-elf.h30
-rw-r--r--gcc-4.2.1/gcc/config/arm/strongarm-pe.h23
-rw-r--r--gcc-4.2.1/gcc/config/arm/symbian.h101
-rw-r--r--gcc-4.2.1/gcc/config/arm/t-arm22
-rw-r--r--gcc-4.2.1/gcc/config/arm/t-arm-coff35
-rw-r--r--gcc-4.2.1/gcc/config/arm/t-arm-elf116
-rw-r--r--gcc-4.2.1/gcc/config/arm/t-bpabi22
-rw-r--r--gcc-4.2.1/gcc/config/arm/t-linux21
-rw-r--r--gcc-4.2.1/gcc/config/arm/t-linux-eabi20
-rw-r--r--gcc-4.2.1/gcc/config/arm/t-netbsd28
-rw-r--r--gcc-4.2.1/gcc/config/arm/t-pe33
-rw-r--r--gcc-4.2.1/gcc/config/arm/t-rtems10
-rw-r--r--gcc-4.2.1/gcc/config/arm/t-semi38
-rw-r--r--gcc-4.2.1/gcc/config/arm/t-strongarm-elf44
-rw-r--r--gcc-4.2.1/gcc/config/arm/t-strongarm-pe38
-rw-r--r--gcc-4.2.1/gcc/config/arm/t-symbian32
-rw-r--r--gcc-4.2.1/gcc/config/arm/t-vxworks10
-rw-r--r--gcc-4.2.1/gcc/config/arm/t-wince-pe38
-rw-r--r--gcc-4.2.1/gcc/config/arm/t-xscale-coff46
-rw-r--r--gcc-4.2.1/gcc/config/arm/t-xscale-elf67
-rw-r--r--gcc-4.2.1/gcc/config/arm/uclinux-elf.h74
-rw-r--r--gcc-4.2.1/gcc/config/arm/unaligned-funcs.c62
-rw-r--r--gcc-4.2.1/gcc/config/arm/unknown-elf.h101
-rw-r--r--gcc-4.2.1/gcc/config/arm/unwind-arm.c1076
-rw-r--r--gcc-4.2.1/gcc/config/arm/unwind-arm.h277
-rw-r--r--gcc-4.2.1/gcc/config/arm/vfp.md841
-rw-r--r--gcc-4.2.1/gcc/config/arm/vxworks.h95
-rw-r--r--gcc-4.2.1/gcc/config/arm/wince-pe.h27
-rw-r--r--gcc-4.2.1/gcc/config/arm/xscale-coff.h34
-rw-r--r--gcc-4.2.1/gcc/config/arm/xscale-elf.h59
85 files changed, 0 insertions, 46445 deletions
diff --git a/gcc-4.2.1/gcc/config/arm/README-interworking b/gcc-4.2.1/gcc/config/arm/README-interworking
deleted file mode 100644
index d221e1555..000000000
--- a/gcc-4.2.1/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. e.g.:
-
- .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 initialized 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
-outside 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-4.2.1/gcc/config/arm/aof.h b/gcc-4.2.1/gcc/config/arm/aof.h
deleted file mode 100644
index 8a1223c45..000000000
--- a/gcc-4.2.1/gcc/config/arm/aof.h
+++ /dev/null
@@ -1,296 +0,0 @@
-/* Definitions of target machine for GNU compiler, for Advanced RISC Machines
- ARM compilation, AOF Assembler.
- Copyright (C) 1995, 1996, 1997, 2000, 2003, 2004
- Free Software Foundation, Inc.
- Contributed by Richard Earnshaw (rearnsha@armltd.co.uk)
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-
-
-#define AOF_ASSEMBLER
-
-#define LINK_LIBGCC_SPECIAL 1
-
-#define LINK_SPEC "%{aof} %{bin} %{aif} %{ihf} %{shl,*} %{reent*} %{split} \
- %{ov*} %{reloc*} -nodebug"
-
-#define STARTFILE_SPEC "crtbegin.o%s"
-
-#define ENDFILE_SPEC "crtend.o%s"
-
-#ifndef ASM_SPEC
-#define ASM_SPEC "%{g -g} -arch 4 -apcs 3/32bit"
-#endif
-
-#ifndef LIB_SPEC
-#define LIB_SPEC "%{Eb: armlib_h.32b%s}%{!Eb: armlib_h.32l%s}"
-#endif
-
-#define LIBGCC_SPEC "libgcc.a%s"
-
-#define CTOR_LIST_BEGIN \
- asm (CTORS_SECTION_ASM_OP); \
- extern func_ptr __CTOR_END__[1]; \
- func_ptr __CTOR_LIST__[1] = {__CTOR_END__};
-
-#define CTOR_LIST_END \
- asm (CTORS_SECTION_ASM_OP); \
- func_ptr __CTOR_END__[1] = { (func_ptr) 0 };
-
-#define DO_GLOBAL_CTORS_BODY \
- do \
- { \
- func_ptr *ptr = __CTOR_LIST__ + 1; \
- \
- while (*ptr) \
- (*ptr++) (); \
- } \
- while (0)
-
-#define DTOR_LIST_BEGIN \
- asm (DTORS_SECTION_ASM_OP); \
- extern func_ptr __DTOR_END__[1]; \
- func_ptr __DTOR_LIST__[1] = {__DTOR_END__};
-
-#define DTOR_LIST_END \
- asm (DTORS_SECTION_ASM_OP); \
- func_ptr __DTOR_END__[1] = { (func_ptr) 0 };
-
-#define DO_GLOBAL_DTORS_BODY \
- do \
- { \
- func_ptr *ptr = __DTOR_LIST__ + 1; \
- \
- while (*ptr) \
- (*ptr++) (); \
- } \
- while (0)
-
-/* We really want to put Thumb tables in a read-only data section, but
- switching to another section during function output is not
- possible. We could however do what the SPARC does and defer the
- whole table generation until the end of the function. */
-#define JUMP_TABLES_IN_TEXT_SECTION 1
-
-#define TARGET_ASM_INIT_SECTIONS aof_asm_init_sections
-
-/* Some systems use __main in a way incompatible with its use in gcc, in these
- cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
- give the same symbol without quotes for an alternative entry point. You
- must define both, or neither. */
-#define NAME__MAIN "__gccmain"
-#define SYMBOL__MAIN __gccmain
-
-#define ASM_COMMENT_START ";"
-#define ASM_APP_ON ""
-#define ASM_APP_OFF ""
-
-#define ASM_OUTPUT_ASCII(STREAM, PTR, LEN) \
-{ \
- int i; \
- const char *ptr = (PTR); \
- fprintf ((STREAM), "\tDCB"); \
- for (i = 0; i < (long)(LEN); i++) \
- fprintf ((STREAM), " &%02x%s", \
- (unsigned ) *(ptr++), \
- (i + 1 < (long)(LEN) \
- ? ((i & 3) == 3 ? "\n\tDCB" : ",") \
- : "\n")); \
-}
-
-#define IS_ASM_LOGICAL_LINE_SEPARATOR(C) ((C) == '\n')
-
-/* Output of Uninitialized Variables. */
-
-#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \
- (in_section = NULL, \
- fprintf ((STREAM), "\tAREA "), \
- assemble_name ((STREAM), (NAME)), \
- fprintf ((STREAM), ", DATA, COMMON\n\t%% %d\t%s size=%d\n", \
- (int)(ROUNDED), ASM_COMMENT_START, (int)(SIZE)))
-
-#define ASM_OUTPUT_LOCAL(STREAM, NAME, SIZE, ROUNDED) \
- (zero_init_section (), \
- assemble_name ((STREAM), (NAME)), \
- fprintf ((STREAM), "\n"), \
- fprintf ((STREAM), "\t%% %d\t%s size=%d\n", \
- (int)(ROUNDED), ASM_COMMENT_START, (int)(SIZE)))
-
-/* Output and Generation of Labels */
-extern int arm_main_function;
-
-/* Globalizing directive for a label. */
-#define GLOBAL_ASM_OP "\tEXPORT\t"
-
-#define ASM_OUTPUT_LABEL(STREAM,NAME) \
-do { \
- assemble_name (STREAM,NAME); \
- fputs ("\n", STREAM); \
-} while (0)
-
-#define ASM_DECLARE_FUNCTION_NAME(STREAM,NAME,DECL) \
-{ \
- if (TARGET_POKE_FUNCTION_NAME) \
- arm_poke_function_name ((STREAM), (NAME)); \
- ASM_OUTPUT_LABEL (STREAM, NAME); \
- if (! TREE_PUBLIC (DECL)) \
- { \
- fputs ("\tKEEP ", STREAM); \
- ASM_OUTPUT_LABEL (STREAM, NAME); \
- } \
- aof_delete_import ((NAME)); \
-}
-
-#define ASM_DECLARE_OBJECT_NAME(STREAM,NAME,DECL) \
-{ \
- ASM_OUTPUT_LABEL (STREAM, NAME); \
- if (! TREE_PUBLIC (DECL)) \
- { \
- fputs ("\tKEEP ", STREAM); \
- ASM_OUTPUT_LABEL (STREAM, NAME); \
- } \
- aof_delete_import ((NAME)); \
-}
-
-#define ASM_OUTPUT_EXTERNAL(STREAM,DECL,NAME) \
- aof_add_import ((NAME))
-
-#define ASM_OUTPUT_EXTERNAL_LIBCALL(STREAM,SYMREF) \
- (fprintf ((STREAM), "\tIMPORT\t"), \
- assemble_name ((STREAM), XSTR ((SYMREF), 0)), \
- fputc ('\n', (STREAM)))
-
-#define ASM_OUTPUT_LABELREF(STREAM,NAME) \
- fprintf ((STREAM), "|%s|", NAME)
-
-#define ASM_GENERATE_INTERNAL_LABEL(STRING,PREFIX,NUM) \
- sprintf ((STRING), "*|%s..%ld|", (PREFIX), (long)(NUM))
-
-/* How initialization functions are handled. */
-
-#define CTORS_SECTION_ASM_OP "\tAREA\t|C$$gnu_ctorsvec|, DATA, READONLY"
-#define DTORS_SECTION_ASM_OP "\tAREA\t|C$$gnu_dtorsvec|, DATA, READONLY"
-
-/* Output of Assembler Instructions. */
-
-#define REGISTER_NAMES \
-{ \
- "a1", "a2", "a3", "a4", \
- "v1", "v2", "v3", "v4", \
- "v5", "v6", "sl", "fp", \
- "ip", "sp", "lr", "pc", \
- "f0", "f1", "f2", "f3", \
- "f4", "f5", "f6", "f7", \
- "cc", "sfp", "afp", \
- "mv0", "mv1", "mv2", "mv3", \
- "mv4", "mv5", "mv6", "mv7", \
- "mv8", "mv9", "mv10", "mv11", \
- "mv12", "mv13", "mv14", "mv15", \
- "wcgr0", "wcgr1", "wcgr2", "wcgr3", \
- "wr0", "wr1", "wr2", "wr3", \
- "wr4", "wr5", "wr6", "wr7", \
- "wr8", "wr9", "wr10", "wr11", \
- "wr12", "wr13", "wr14", "wr15", \
- "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", \
- "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15", \
- "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", \
- "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", \
- "vfpcc" \
-}
-
-#define ADDITIONAL_REGISTER_NAMES \
-{ \
- {"r0", 0}, {"a1", 0}, \
- {"r1", 1}, {"a2", 1}, \
- {"r2", 2}, {"a3", 2}, \
- {"r3", 3}, {"a4", 3}, \
- {"r4", 4}, {"v1", 4}, \
- {"r5", 5}, {"v2", 5}, \
- {"r6", 6}, {"v3", 6}, \
- {"r7", 7}, {"wr", 7}, \
- {"r8", 8}, {"v5", 8}, \
- {"r9", 9}, {"v6", 9}, \
- {"r10", 10}, {"sl", 10}, {"v7", 10}, \
- {"r11", 11}, {"fp", 11}, \
- {"r12", 12}, {"ip", 12}, \
- {"r13", 13}, {"sp", 13}, \
- {"r14", 14}, {"lr", 14}, \
- {"r15", 15}, {"pc", 15}, \
- {"d0", 63}, \
- {"d1", 65}, \
- {"d2", 67}, \
- {"d3", 69}, \
- {"d4", 71}, \
- {"d5", 73}, \
- {"d6", 75}, \
- {"d7", 77}, \
- {"d8", 79}, \
- {"d9", 81}, \
- {"d10", 83}, \
- {"d11", 85}, \
- {"d12", 87}, \
- {"d13", 89}, \
- {"d14", 91}, \
- {"d15", 93} \
-}
-
-#define REGISTER_PREFIX "__"
-#define USER_LABEL_PREFIX ""
-#define LOCAL_LABEL_PREFIX ""
-
-/* AOF does not prefix user function names with an underscore. */
-#define ARM_MCOUNT_NAME "_mcount"
-
-/* Output of Dispatch Tables. */
-#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \
- do \
- { \
- if (TARGET_ARM) \
- fprintf ((STREAM), "\tb\t|L..%d|\n", (VALUE)); \
- else \
- fprintf ((STREAM), "\tDCD\t|L..%d| - |L..%d|\n", (VALUE), (REL)); \
- } \
- while (0)
-
-#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
- fprintf ((STREAM), "\tDCD\t|L..%d|\n", (VALUE))
-
-/* A label marking the start of a jump table is a data label. */
-#define ASM_OUTPUT_CASE_LABEL(STREAM, PREFIX, NUM, TABLE) \
- fprintf ((STREAM), "\tALIGN\n|%s..%d|\n", (PREFIX), (NUM))
-
-/* Assembler Commands for Alignment. */
-#define ASM_OUTPUT_SKIP(STREAM, NBYTES) \
- fprintf ((STREAM), "\t%%\t%d\n", (int) (NBYTES))
-
-#define ASM_OUTPUT_ALIGN(STREAM, POWER) \
- do \
- { \
- int amount = 1 << (POWER); \
- \
- if (amount == 2) \
- fprintf ((STREAM), "\tALIGN 2\n"); \
- else if (amount == 4) \
- fprintf ((STREAM), "\tALIGN\n"); \
- else \
- fprintf ((STREAM), "\tALIGN %d\n", amount); \
- } \
- while (0)
-
-#undef DBX_DEBUGGING_INFO
diff --git a/gcc-4.2.1/gcc/config/arm/aout.h b/gcc-4.2.1/gcc/config/arm/aout.h
deleted file mode 100644
index 903afa70f..000000000
--- a/gcc-4.2.1/gcc/config/arm/aout.h
+++ /dev/null
@@ -1,301 +0,0 @@
-/* Definitions of target machine for GNU compiler, for ARM with a.out
- Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2004
- Free Software Foundation, Inc.
- Contributed by Richard Earnshaw (rearnsha@armltd.co.uk).
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-#ifndef ASM_APP_ON
-#define ASM_APP_ON ""
-#endif
-#ifndef ASM_APP_OFF
-#define ASM_APP_OFF ""
-#endif
-
-/* Switch to the text or data segment. */
-#define TEXT_SECTION_ASM_OP "\t.text"
-#define DATA_SECTION_ASM_OP "\t.data"
-#define BSS_SECTION_ASM_OP "\t.bss"
-
-/* Note: If USER_LABEL_PREFIX or LOCAL_LABEL_PREFIX are changed,
- make sure that this change is reflected in the function
- coff_arm_is_local_label_name() in bfd/coff-arm.c. */
-#ifndef REGISTER_PREFIX
-#define REGISTER_PREFIX ""
-#endif
-
-#ifndef USER_LABEL_PREFIX
-#define USER_LABEL_PREFIX "_"
-#endif
-
-#ifndef LOCAL_LABEL_PREFIX
-#define LOCAL_LABEL_PREFIX ""
-#endif
-
-/* 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", \
- "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
- "cc", "sfp", "afp", \
- "mv0", "mv1", "mv2", "mv3", \
- "mv4", "mv5", "mv6", "mv7", \
- "mv8", "mv9", "mv10", "mv11", \
- "mv12", "mv13", "mv14", "mv15", \
- "wcgr0", "wcgr1", "wcgr2", "wcgr3", \
- "wr0", "wr1", "wr2", "wr3", \
- "wr4", "wr5", "wr6", "wr7", \
- "wr8", "wr9", "wr10", "wr11", \
- "wr12", "wr13", "wr14", "wr15", \
- "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", \
- "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15", \
- "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", \
- "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", \
- "vfpcc" \
-}
-#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}, \
- {"rfp", 9}, /* Gcc used to call it this */ \
- {"sb", 9}, \
- {"v7", 10}, \
- {"r10", 10}, /* sl */ \
- {"r11", 11}, /* fp */ \
- {"r12", 12}, /* ip */ \
- {"r13", 13}, /* sp */ \
- {"r14", 14}, /* lr */ \
- {"r15", 15}, /* pc */ \
- {"mvf0", 27}, \
- {"mvf1", 28}, \
- {"mvf2", 29}, \
- {"mvf3", 30}, \
- {"mvf4", 31}, \
- {"mvf5", 32}, \
- {"mvf6", 33}, \
- {"mvf7", 34}, \
- {"mvf8", 35}, \
- {"mvf9", 36}, \
- {"mvf10", 37}, \
- {"mvf11", 38}, \
- {"mvf12", 39}, \
- {"mvf13", 40}, \
- {"mvf14", 41}, \
- {"mvf15", 42}, \
- {"mvd0", 27}, \
- {"mvd1", 28}, \
- {"mvd2", 29}, \
- {"mvd3", 30}, \
- {"mvd4", 31}, \
- {"mvd5", 32}, \
- {"mvd6", 33}, \
- {"mvd7", 34}, \
- {"mvd8", 35}, \
- {"mvd9", 36}, \
- {"mvd10", 37}, \
- {"mvd11", 38}, \
- {"mvd12", 39}, \
- {"mvd13", 40}, \
- {"mvd14", 41}, \
- {"mvd15", 42}, \
- {"mvfx0", 27}, \
- {"mvfx1", 28}, \
- {"mvfx2", 29}, \
- {"mvfx3", 30}, \
- {"mvfx4", 31}, \
- {"mvfx5", 32}, \
- {"mvfx6", 33}, \
- {"mvfx7", 34}, \
- {"mvfx8", 35}, \
- {"mvfx9", 36}, \
- {"mvfx10", 37}, \
- {"mvfx11", 38}, \
- {"mvfx12", 39}, \
- {"mvfx13", 40}, \
- {"mvfx14", 41}, \
- {"mvfx15", 42}, \
- {"mvdx0", 27}, \
- {"mvdx1", 28}, \
- {"mvdx2", 29}, \
- {"mvdx3", 30}, \
- {"mvdx4", 31}, \
- {"mvdx5", 32}, \
- {"mvdx6", 33}, \
- {"mvdx7", 34}, \
- {"mvdx8", 35}, \
- {"mvdx9", 36}, \
- {"mvdx10", 37}, \
- {"mvdx11", 38}, \
- {"mvdx12", 39}, \
- {"mvdx13", 40}, \
- {"mvdx14", 41}, \
- {"mvdx15", 42}, \
- {"d0", 63}, \
- {"d1", 65}, \
- {"d2", 67}, \
- {"d3", 69}, \
- {"d4", 71}, \
- {"d5", 73}, \
- {"d6", 75}, \
- {"d7", 77}, \
- {"d8", 79}, \
- {"d9", 81}, \
- {"d10", 83}, \
- {"d11", 85}, \
- {"d12", 87}, \
- {"d13", 89}, \
- {"d14", 91}, \
- {"d15", 93}, \
-}
-#endif
-
-/* Arm Assembler barfs on dollars. */
-#define DOLLARS_IN_IDENTIFIERS 0
-
-#ifndef NO_DOLLAR_IN_LABEL
-#define NO_DOLLAR_IN_LABEL 1
-#endif
-
-/* Generate DBX debugging information. riscix.h will undefine this because
- the native assembler does not support stabs. */
-#define DBX_DEBUGGING_INFO 1
-
-/* Acorn dbx moans about continuation chars, so don't use any. */
-#ifndef DBX_CONTIN_LENGTH
-#define DBX_CONTIN_LENGTH 0
-#endif
-
-/* Output a function label definition. */
-#ifndef ASM_DECLARE_FUNCTION_NAME
-#define ASM_DECLARE_FUNCTION_NAME(STREAM, NAME, DECL) \
- do \
- { \
- ARM_DECLARE_FUNCTION_NAME (STREAM, NAME, DECL); \
- ASM_OUTPUT_LABEL (STREAM, NAME); \
- } \
- while (0)
-#endif
-
-/* Globalizing directive for a label. */
-#define GLOBAL_ASM_OP "\t.global\t"
-
-/* Make an internal label into a string. */
-#ifndef ASM_GENERATE_INTERNAL_LABEL
-#define ASM_GENERATE_INTERNAL_LABEL(STRING, PREFIX, NUM) \
- sprintf (STRING, "*%s%s%u", LOCAL_LABEL_PREFIX, PREFIX, (unsigned int)(NUM))
-#endif
-
-/* Output an element of a dispatch table. */
-#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
- asm_fprintf (STREAM, "\t.word\t%LL%d\n", VALUE)
-
-#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \
- do \
- { \
- if (TARGET_ARM) \
- asm_fprintf (STREAM, "\tb\t%LL%d\n", VALUE); \
- else \
- asm_fprintf (STREAM, "\t.word\t%LL%d-%LL%d\n", VALUE, REL); \
- } \
- while (0)
-
-
-#undef ASM_OUTPUT_ASCII
-#define ASM_OUTPUT_ASCII(STREAM, PTR, LEN) \
- output_ascii_pseudo_op (STREAM, (const unsigned char *) (PTR), LEN)
-
-/* Output a gap. In fact we fill it with nulls. */
-#undef ASM_OUTPUT_SKIP
-#define ASM_OUTPUT_SKIP(STREAM, NBYTES) \
- fprintf (STREAM, "\t.space\t%d\n", (int) (NBYTES))
-
-/* Align output to a power of two. Horrible /bin/as. */
-#ifndef ASM_OUTPUT_ALIGN
-#define ASM_OUTPUT_ALIGN(STREAM, POWER) \
- do \
- { \
- register int amount = 1 << (POWER); \
- \
- if (amount == 2) \
- fprintf (STREAM, "\t.even\n"); \
- else if (amount != 1) \
- fprintf (STREAM, "\t.align\t%d\n", amount - 4); \
- } \
- while (0)
-#endif
-
-/* Output a common block. */
-#ifndef ASM_OUTPUT_COMMON
-#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \
- do \
- { \
- fprintf (STREAM, "\t.comm\t"); \
- assemble_name (STREAM, NAME); \
- asm_fprintf (STREAM, ", %d\t%@ %d\n", \
- (int)(ROUNDED), (int)(SIZE)); \
- } \
- while (0)
-#endif
-
-/* Output a local common block. /bin/as can't do this, so hack a
- `.space' into the bss segment. Note that this is *bad* practice,
- which is guaranteed NOT to work since it doesn't define STATIC
- COMMON space but merely STATIC BSS space. */
-#ifndef ASM_OUTPUT_ALIGNED_LOCAL
-#define ASM_OUTPUT_ALIGNED_LOCAL(STREAM, NAME, SIZE, ALIGN) \
- do \
- { \
- switch_to_section (bss_section); \
- ASM_OUTPUT_ALIGN (STREAM, floor_log2 (ALIGN / BITS_PER_UNIT)); \
- ASM_OUTPUT_LABEL (STREAM, NAME); \
- fprintf (STREAM, "\t.space\t%d\n", (int)(SIZE)); \
- } \
- while (0)
-#endif
-
-/* Output a zero-initialized block. */
-#ifndef ASM_OUTPUT_ALIGNED_BSS
-#define ASM_OUTPUT_ALIGNED_BSS(STREAM, DECL, NAME, SIZE, ALIGN) \
- asm_output_aligned_bss (STREAM, DECL, NAME, SIZE, ALIGN)
-#endif
-
-/* Output a #ident directive. */
-#ifndef ASM_OUTPUT_IDENT
-#define ASM_OUTPUT_IDENT(STREAM,STRING) \
- asm_fprintf (STREAM, "%@ - - - ident %s\n", STRING)
-#endif
-
-#ifndef ASM_COMMENT_START
-#define ASM_COMMENT_START "@"
-#endif
-
-/* This works for GAS and some other assemblers. */
-#define SET_ASM_OP "\t.set\t"
diff --git a/gcc-4.2.1/gcc/config/arm/arm-cores.def b/gcc-4.2.1/gcc/config/arm/arm-cores.def
deleted file mode 100644
index 3f9b7bad4..000000000
--- a/gcc-4.2.1/gcc/config/arm/arm-cores.def
+++ /dev/null
@@ -1,117 +0,0 @@
-/* ARM CPU Cores
- Copyright (C) 2003, 2005 Free Software Foundation, Inc.
- Written by CodeSourcery, LLC
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- GCC is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING. If not, write to the Free
- Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA. */
-
-/* Before using #include to read this file, define a macro:
-
- ARM_CORE(CORE_NAME, CORE_IDENT, ARCH, FLAGS, COSTS)
-
- The CORE_NAME is the name of the core, represented as a string constant.
- The CORE_IDENT is the name of the core, represented as an identifier.
- ARCH is the architecture revision implemented by the chip.
- FLAGS are the bitwise-or of the traits that apply to that core.
- This need not include flags implied by the architecture.
- COSTS is the name of the rtx_costs routine to use.
-
- If you update this table, you must update the "tune" attribute in
- arm.md.
-
- Some tools assume no whitespace up to the first "," in each entry. */
-
-/* V2/V2A Architecture Processors */
-ARM_CORE("arm2", arm2, 2, FL_CO_PROC | FL_MODE26, slowmul)
-ARM_CORE("arm250", arm250, 2, FL_CO_PROC | FL_MODE26, slowmul)
-ARM_CORE("arm3", arm3, 2, FL_CO_PROC | FL_MODE26, slowmul)
-
-/* V3 Architecture Processors */
-ARM_CORE("arm6", arm6, 3, FL_CO_PROC | FL_MODE26, slowmul)
-ARM_CORE("arm60", arm60, 3, FL_CO_PROC | FL_MODE26, slowmul)
-ARM_CORE("arm600", arm600, 3, FL_CO_PROC | FL_MODE26 | FL_WBUF, slowmul)
-ARM_CORE("arm610", arm610, 3, FL_MODE26 | FL_WBUF, slowmul)
-ARM_CORE("arm620", arm620, 3, FL_CO_PROC | FL_MODE26 | FL_WBUF, slowmul)
-ARM_CORE("arm7", arm7, 3, FL_CO_PROC | FL_MODE26, slowmul)
-ARM_CORE("arm7d", arm7d, 3, FL_CO_PROC | FL_MODE26, slowmul)
-ARM_CORE("arm7di", arm7di, 3, FL_CO_PROC | FL_MODE26, slowmul)
-ARM_CORE("arm70", arm70, 3, FL_CO_PROC | FL_MODE26, slowmul)
-ARM_CORE("arm700", arm700, 3, FL_CO_PROC | FL_MODE26 | FL_WBUF, slowmul)
-ARM_CORE("arm700i", arm700i, 3, FL_CO_PROC | FL_MODE26 | FL_WBUF, slowmul)
-ARM_CORE("arm710", arm710, 3, FL_MODE26 | FL_WBUF, slowmul)
-ARM_CORE("arm720", arm720, 3, FL_MODE26 | FL_WBUF, slowmul)
-ARM_CORE("arm710c", arm710c, 3, FL_MODE26 | FL_WBUF, slowmul)
-ARM_CORE("arm7100", arm7100, 3, FL_MODE26 | FL_WBUF, slowmul)
-ARM_CORE("arm7500", arm7500, 3, FL_MODE26 | FL_WBUF, slowmul)
-/* Doesn't have an external co-proc, but does have embedded fpa. */
-ARM_CORE("arm7500fe", arm7500fe, 3, FL_CO_PROC | FL_MODE26 | FL_WBUF, slowmul)
-
-/* V3M Architecture Processors */
-/* arm7m doesn't exist on its own, but only with D, ("and", and I), but
- those don't alter the code, so arm7m is sometimes used. */
-ARM_CORE("arm7m", arm7m, 3M, FL_CO_PROC | FL_MODE26, fastmul)
-ARM_CORE("arm7dm", arm7dm, 3M, FL_CO_PROC | FL_MODE26, fastmul)
-ARM_CORE("arm7dmi", arm7dmi, 3M, FL_CO_PROC | FL_MODE26, fastmul)
-
-/* V4 Architecture Processors */
-ARM_CORE("arm8", arm8, 4, FL_MODE26 | FL_LDSCHED, fastmul)
-ARM_CORE("arm810", arm810, 4, FL_MODE26 | FL_LDSCHED, fastmul)
-ARM_CORE("strongarm", strongarm, 4, FL_MODE26 | FL_LDSCHED | FL_STRONG, fastmul)
-ARM_CORE("strongarm110", strongarm110, 4, FL_MODE26 | FL_LDSCHED | FL_STRONG, fastmul)
-ARM_CORE("strongarm1100", strongarm1100, 4, FL_MODE26 | FL_LDSCHED | FL_STRONG, fastmul)
-ARM_CORE("strongarm1110", strongarm1110, 4, FL_MODE26 | FL_LDSCHED | FL_STRONG, fastmul)
-
-/* V4T Architecture Processors */
-ARM_CORE("arm7tdmi", arm7tdmi, 4T, FL_CO_PROC , fastmul)
-ARM_CORE("arm7tdmi-s", arm7tdmis, 4T, FL_CO_PROC , fastmul)
-ARM_CORE("arm710t", arm710t, 4T, FL_WBUF, fastmul)
-ARM_CORE("arm720t", arm720t, 4T, FL_WBUF, fastmul)
-ARM_CORE("arm740t", arm740t, 4T, FL_WBUF, fastmul)
-ARM_CORE("arm9", arm9, 4T, FL_LDSCHED, fastmul)
-ARM_CORE("arm9tdmi", arm9tdmi, 4T, FL_LDSCHED, fastmul)
-ARM_CORE("arm920", arm920, 4T, FL_LDSCHED, fastmul)
-ARM_CORE("arm920t", arm920t, 4T, FL_LDSCHED, fastmul)
-ARM_CORE("arm922t", arm922t, 4T, FL_LDSCHED, fastmul)
-ARM_CORE("arm940t", arm940t, 4T, FL_LDSCHED, fastmul)
-ARM_CORE("ep9312", ep9312, 4T, FL_LDSCHED | FL_CIRRUS, fastmul)
-
-/* V5T Architecture Processors */
-ARM_CORE("arm10tdmi", arm10tdmi, 5T, FL_LDSCHED, fastmul)
-ARM_CORE("arm1020t", arm1020t, 5T, FL_LDSCHED, fastmul)
-
-/* V5TE Architecture Processors */
-ARM_CORE("arm9e", arm9e, 5TE, FL_LDSCHED, 9e)
-ARM_CORE("arm946e-s", arm946es, 5TE, FL_LDSCHED, 9e)
-ARM_CORE("arm966e-s", arm966es, 5TE, FL_LDSCHED, 9e)
-ARM_CORE("arm968e-s", arm968es, 5TE, FL_LDSCHED, 9e)
-ARM_CORE("arm10e", arm10e, 5TE, FL_LDSCHED, fastmul)
-ARM_CORE("arm1020e", arm1020e, 5TE, FL_LDSCHED, fastmul)
-ARM_CORE("arm1022e", arm1022e, 5TE, FL_LDSCHED, fastmul)
-ARM_CORE("xscale", xscale, 5TE, FL_LDSCHED | FL_STRONG | FL_XSCALE, xscale)
-ARM_CORE("iwmmxt", iwmmxt, 5TE, FL_LDSCHED | FL_STRONG | FL_XSCALE | FL_IWMMXT, xscale)
-
-/* V5TEJ Architecture Processors */
-ARM_CORE("arm926ej-s", arm926ejs, 5TEJ, FL_LDSCHED, 9e)
-ARM_CORE("arm1026ej-s", arm1026ejs, 5TEJ, FL_LDSCHED, 9e)
-
-/* V6 Architecture Processors */
-ARM_CORE("arm1136j-s", arm1136js, 6J, FL_LDSCHED, 9e)
-ARM_CORE("arm1136jf-s", arm1136jfs, 6J, FL_LDSCHED | FL_VFPV2, 9e)
-ARM_CORE("arm1176jz-s", arm1176jzs, 6ZK, FL_LDSCHED, 9e)
-ARM_CORE("arm1176jzf-s", arm1176jzfs, 6ZK, FL_LDSCHED | FL_VFPV2, 9e)
-ARM_CORE("mpcorenovfp", mpcorenovfp, 6K, FL_LDSCHED, 9e)
-ARM_CORE("mpcore", mpcore, 6K, FL_LDSCHED | FL_VFPV2, 9e)
diff --git a/gcc-4.2.1/gcc/config/arm/arm-generic.md b/gcc-4.2.1/gcc/config/arm/arm-generic.md
deleted file mode 100644
index 611648648..000000000
--- a/gcc-4.2.1/gcc/config/arm/arm-generic.md
+++ /dev/null
@@ -1,152 +0,0 @@
-;; Generic ARM Pipeline Description
-;; Copyright (C) 2003 Free Software Foundation, Inc.
-;;
-;; This file is part of GCC.
-;;
-;; GCC is free software; you can redistribute it and/or modify it
-;; under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-;;
-;; GCC is distributed in the hope that it will be useful, but
-;; WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-;; General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING. If not, write to the Free
-;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-;; 02110-1301, USA. */
-
-(define_automaton "arm")
-
-;; Write buffer
-;
-; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
-;
-; The write buffer on some of the arm6 processors is hard to model exactly.
-; There is room in the buffer for up to two addresses and up to eight words
-; of memory, but the two needn't be split evenly. When writing the two
-; addresses are fully pipelined. However, a read from memory that is not
-; currently in the cache will block until the writes have completed.
-; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
-; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
-; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
-; cycle to add as well.
-(define_cpu_unit "write_buf" "arm")
-
-;; Write blockage unit
-;
-; The write_blockage unit models (partially), the fact that reads will stall
-; until the write buffer empties.
-; The f_mem_r and r_mem_f could also block, but they are to the stack,
-; so we don't model them here
-(define_cpu_unit "write_blockage" "arm")
-
-;; Core
-;
-(define_cpu_unit "core" "arm")
-
-(define_insn_reservation "r_mem_f_wbuf" 5
- (and (eq_attr "generic_sched" "yes")
- (and (eq_attr "model_wbuf" "yes")
- (eq_attr "type" "r_mem_f")))
- "core+write_buf*3")
-
-(define_insn_reservation "store_wbuf" 5
- (and (eq_attr "generic_sched" "yes")
- (and (eq_attr "model_wbuf" "yes")
- (eq_attr "type" "store1")))
- "core+write_buf*3+write_blockage*5")
-
-(define_insn_reservation "store2_wbuf" 7
- (and (eq_attr "generic_sched" "yes")
- (and (eq_attr "model_wbuf" "yes")
- (eq_attr "type" "store2")))
- "core+write_buf*4+write_blockage*7")
-
-(define_insn_reservation "store3_wbuf" 9
- (and (eq_attr "generic_sched" "yes")
- (and (eq_attr "model_wbuf" "yes")
- (eq_attr "type" "store3")))
- "core+write_buf*5+write_blockage*9")
-
-(define_insn_reservation "store4_wbuf" 11
- (and (eq_attr "generic_sched" "yes")
- (and (eq_attr "model_wbuf" "yes")
- (eq_attr "type" "store4")))
- "core+write_buf*6+write_blockage*11")
-
-(define_insn_reservation "store2" 3
- (and (eq_attr "generic_sched" "yes")
- (and (eq_attr "model_wbuf" "no")
- (eq_attr "type" "store2")))
- "core*3")
-
-(define_insn_reservation "store3" 4
- (and (eq_attr "generic_sched" "yes")
- (and (eq_attr "model_wbuf" "no")
- (eq_attr "type" "store3")))
- "core*4")
-
-(define_insn_reservation "store4" 5
- (and (eq_attr "generic_sched" "yes")
- (and (eq_attr "model_wbuf" "no")
- (eq_attr "type" "store4")))
- "core*5")
-
-(define_insn_reservation "store_ldsched" 1
- (and (eq_attr "generic_sched" "yes")
- (and (eq_attr "ldsched" "yes")
- (eq_attr "type" "store1")))
- "core")
-
-(define_insn_reservation "load_ldsched_xscale" 3
- (and (eq_attr "generic_sched" "yes")
- (and (eq_attr "ldsched" "yes")
- (and (eq_attr "type" "load_byte,load1")
- (eq_attr "is_xscale" "yes"))))
- "core")
-
-(define_insn_reservation "load_ldsched" 2
- (and (eq_attr "generic_sched" "yes")
- (and (eq_attr "ldsched" "yes")
- (and (eq_attr "type" "load_byte,load1")
- (eq_attr "is_xscale" "no"))))
- "core")
-
-(define_insn_reservation "load_or_store" 2
- (and (eq_attr "generic_sched" "yes")
- (and (eq_attr "ldsched" "!yes")
- (eq_attr "type" "load_byte,load1,load2,load3,load4,store1")))
- "core*2")
-
-(define_insn_reservation "mult" 16
- (and (eq_attr "generic_sched" "yes")
- (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")))
- "core*16")
-
-(define_insn_reservation "mult_ldsched_strongarm" 3
- (and (eq_attr "generic_sched" "yes")
- (and (eq_attr "ldsched" "yes")
- (and (eq_attr "is_strongarm" "yes")
- (eq_attr "type" "mult"))))
- "core*2")
-
-(define_insn_reservation "mult_ldsched" 4
- (and (eq_attr "generic_sched" "yes")
- (and (eq_attr "ldsched" "yes")
- (and (eq_attr "is_strongarm" "no")
- (eq_attr "type" "mult"))))
- "core*4")
-
-(define_insn_reservation "multi_cycle" 32
- (and (eq_attr "generic_sched" "yes")
- (and (eq_attr "core_cycles" "multi")
- (eq_attr "type" "!mult,load_byte,load1,load2,load3,load4,store1,store2,store3,store4")))
- "core*32")
-
-(define_insn_reservation "single_cycle" 1
- (and (eq_attr "generic_sched" "yes")
- (eq_attr "core_cycles" "single"))
- "core")
diff --git a/gcc-4.2.1/gcc/config/arm/arm-libgcc2.c b/gcc-4.2.1/gcc/config/arm/arm-libgcc2.c
deleted file mode 100644
index d81cc5080..000000000
--- a/gcc-4.2.1/gcc/config/arm/arm-libgcc2.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/* This file contains libgcc2 functions we want to override for the
- ARM target. */
-
-/* Copyright (C) 2008 Free Software Foundation, Inc.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 2, or (at your option) any later
- version.
-
- 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 into combinations with other programs,
- and to distribute those combinations 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 a combine
- executable.)
-
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING. If not, write to the Free
- Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA. */
-
-#include "tconfig.h"
-#include "tsystem.h"
-#include "coretypes.h"
-#include "tm.h"
-
-#ifdef HAVE_GAS_HIDDEN
-#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden")))
-#else
-#define ATTRIBUTE_HIDDEN
-#endif
-
-#ifndef MIN_UNITS_PER_WORD
-#define MIN_UNITS_PER_WORD UNITS_PER_WORD
-#endif
-
-#define LIBGCC2_UNITS_PER_WORD UNITS_PER_WORD
-
-#include "libgcc2.h"
-#undef int
-
-#define __ARM_ARCH__ 3
-
-#if defined(__ARM_ARCH_3M__) || defined(__ARM_ARCH_4__) \
- || defined(__ARM_ARCH_4T__)
-/* We use __ARM_ARCH__ set to 4 here, but in reality it's any processor with
- long multiply instructions. That includes v3M. */
-# undef __ARM_ARCH__
-# define __ARM_ARCH__ 4
-#endif
-
-#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
- || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
- || defined(__ARM_ARCH_5TEJ__)
-# undef __ARM_ARCH__
-# define __ARM_ARCH__ 5
-#endif
-
-#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
- || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
- || defined(__ARM_ARCH_6ZK__)
-# undef __ARM_ARCH__
-# define __ARM_ARCH__ 6
-#endif
-
-#ifndef __ARM_ARCH__
-#error Unable to determine architecture.
-#endif
-
-/* The CLZ instruction is only available for some v5 architectures. */
-
-#if __ARM_ARCH__ < 6 \
- && !defined(__ARM_ARCH_5E__) && !defined(__ARM_ARCH_5TE__) \
- && !defined(__ARM_ARCH_5TEJ__)
-
-/* The C implementations of the clz*2 functions are only compiled for
- architectures which lack the clz instruction. For architectures
- with the DSP extension, we use the ones in lib1funcs.asm. */
-
-int
-__clzsi2 (USItype x)
-{
- Wtype ret;
-
- count_leading_zeros (ret, x);
-
- return ret;
-}
-
-int
-__clzdi2 (UDItype x)
-{
- const DWunion uu = {.ll = x};
- UWtype word;
- Wtype ret, add;
-
- if (uu.s.high)
- word = uu.s.high, add = 0;
- else
- word = uu.s.low, add = W_TYPE_SIZE;
-
- count_leading_zeros (ret, word);
- return ret + add;
-}
-
-#endif /* __ARM_ARCH__ < 6 */ \
- /* && !defined(__ARM_ARCH_5E__) && !defined(__ARM_ARCH_5TE__) */ \
- /* && !defined(__ARM_ARCH_5TEJ__) */
diff --git a/gcc-4.2.1/gcc/config/arm/arm-modes.def b/gcc-4.2.1/gcc/config/arm/arm-modes.def
deleted file mode 100644
index 10ba02576..000000000
--- a/gcc-4.2.1/gcc/config/arm/arm-modes.def
+++ /dev/null
@@ -1,60 +0,0 @@
-/* Definitions of target machine for GNU compiler, for ARM.
- Copyright (C) 2002, 2004 Free Software Foundation, Inc.
- Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
- and Martin Simmons (@harleqn.co.uk).
- More major hacks by Richard Earnshaw (rearnsha@arm.com)
- Minor hacks by Nick Clifton (nickc@cygnus.com)
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* Extended precision floating point.
- FIXME What format is this? */
-FLOAT_MODE (XF, 12, 0);
-
-/* CCFPEmode should be used with floating inequalities,
- CCFPmode should be used with floating equalities.
- CC_NOOVmode should be used with SImode integer equalities.
- CC_Zmode should be used if only the Z flag is set correctly
- CC_Nmode should be used if only the N (sign) flag is set correctly
- CCmode should be used otherwise. */
-
-CC_MODE (CC_NOOV);
-CC_MODE (CC_Z);
-CC_MODE (CC_SWP);
-CC_MODE (CCFP);
-CC_MODE (CCFPE);
-CC_MODE (CC_DNE);
-CC_MODE (CC_DEQ);
-CC_MODE (CC_DLE);
-CC_MODE (CC_DLT);
-CC_MODE (CC_DGE);
-CC_MODE (CC_DGT);
-CC_MODE (CC_DLEU);
-CC_MODE (CC_DLTU);
-CC_MODE (CC_DGEU);
-CC_MODE (CC_DGTU);
-CC_MODE (CC_C);
-CC_MODE (CC_N);
-
-/* Vector modes. */
-VECTOR_MODES (INT, 4); /* V4QI V2HI */
-VECTOR_MODES (INT, 8); /* V8QI V4HI V2SI */
-VECTOR_MODES (INT, 16); /* V16QI V8HI V4SI V2DI */
-VECTOR_MODES (FLOAT, 8); /* V4HF V2SF */
-VECTOR_MODES (FLOAT, 16); /* V8HF V4SF V2DF */
-
diff --git a/gcc-4.2.1/gcc/config/arm/arm-protos.h b/gcc-4.2.1/gcc/config/arm/arm-protos.h
deleted file mode 100644
index c8c119e57..000000000
--- a/gcc-4.2.1/gcc/config/arm/arm-protos.h
+++ /dev/null
@@ -1,191 +0,0 @@
-/* Prototypes for exported functions defined in arm.c and pe.c
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
- Free Software Foundation, Inc.
- Contributed by Richard Earnshaw (rearnsha@arm.com)
- Minor hacks by Nick Clifton (nickc@cygnus.com)
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- GCC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-#ifndef GCC_ARM_PROTOS_H
-#define GCC_ARM_PROTOS_H
-
-extern void arm_override_options (void);
-extern int use_return_insn (int, rtx);
-extern int arm_regno_class (int);
-extern void arm_load_pic_register (unsigned long);
-extern int arm_volatile_func (void);
-extern const char *arm_output_epilogue (rtx);
-extern void arm_expand_prologue (void);
-extern const char *arm_strip_name_encoding (const char *);
-extern void arm_asm_output_labelref (FILE *, const char *);
-extern unsigned long arm_current_func_type (void);
-extern HOST_WIDE_INT arm_compute_initial_elimination_offset (unsigned int,
- unsigned int);
-extern HOST_WIDE_INT thumb_compute_initial_elimination_offset (unsigned int,
- unsigned int);
-extern unsigned int arm_dbx_register_number (unsigned int);
-extern void arm_output_fn_unwind (FILE *, bool);
-
-
-#ifdef TREE_CODE
-extern int arm_return_in_memory (tree);
-extern void arm_encode_call_attribute (tree, int);
-#endif
-#ifdef RTX_CODE
-extern bool arm_vector_mode_supported_p (enum machine_mode);
-extern int arm_hard_regno_mode_ok (unsigned int, enum machine_mode);
-extern int const_ok_for_arm (HOST_WIDE_INT);
-extern int arm_split_constant (RTX_CODE, enum machine_mode, rtx,
- HOST_WIDE_INT, rtx, rtx, int);
-extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, enum machine_mode,
- rtx *);
-extern int legitimate_pic_operand_p (rtx);
-extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
-extern rtx legitimize_tls_address (rtx, rtx);
-extern int arm_legitimate_address_p (enum machine_mode, rtx, RTX_CODE, int);
-extern int thumb_legitimate_address_p (enum machine_mode, rtx, int);
-extern int thumb_legitimate_offset_p (enum machine_mode, HOST_WIDE_INT);
-extern rtx arm_legitimize_address (rtx, rtx, enum machine_mode);
-extern rtx thumb_legitimize_address (rtx, rtx, enum machine_mode);
-extern rtx thumb_legitimize_reload_address (rtx *, enum machine_mode, int, int,
- int);
-extern int arm_const_double_rtx (rtx);
-extern int neg_const_double_rtx_ok_for_fpa (rtx);
-extern enum reg_class coproc_secondary_reload_class (enum machine_mode, rtx,
- bool);
-extern bool arm_tls_referenced_p (rtx);
-
-extern int cirrus_memory_offset (rtx);
-extern int arm_coproc_mem_operand (rtx, bool);
-extern int arm_no_early_store_addr_dep (rtx, rtx);
-extern int arm_no_early_alu_shift_dep (rtx, rtx);
-extern int arm_no_early_alu_shift_value_dep (rtx, rtx);
-extern int arm_no_early_mul_dep (rtx, rtx);
-
-extern int tls_mentioned_p (rtx);
-extern int symbol_mentioned_p (rtx);
-extern int label_mentioned_p (rtx);
-extern RTX_CODE minmax_code (rtx);
-extern int adjacent_mem_locations (rtx, rtx);
-extern int load_multiple_sequence (rtx *, int, int *, int *, HOST_WIDE_INT *);
-extern const char *emit_ldm_seq (rtx *, int);
-extern int store_multiple_sequence (rtx *, int, int *, int *, HOST_WIDE_INT *);
-extern const char * emit_stm_seq (rtx *, int);
-extern rtx arm_gen_load_multiple (int, int, rtx, int, int,
- rtx, HOST_WIDE_INT *);
-extern rtx arm_gen_store_multiple (int, int, rtx, int, int,
- rtx, HOST_WIDE_INT *);
-extern int arm_gen_movmemqi (rtx *);
-extern enum machine_mode arm_select_cc_mode (RTX_CODE, rtx, rtx);
-extern enum machine_mode arm_select_dominance_cc_mode (rtx, rtx,
- HOST_WIDE_INT);
-extern rtx arm_gen_compare_reg (RTX_CODE, rtx, rtx);
-extern rtx arm_gen_return_addr_mask (void);
-extern void arm_reload_in_hi (rtx *);
-extern void arm_reload_out_hi (rtx *);
-extern int arm_const_double_inline_cost (rtx);
-extern bool arm_const_double_by_parts (rtx);
-extern const char *fp_immediate_constant (rtx);
-extern const char *output_call (rtx *);
-extern const char *output_call_mem (rtx *);
-extern const char *output_mov_long_double_fpa_from_arm (rtx *);
-extern const char *output_mov_long_double_arm_from_fpa (rtx *);
-extern const char *output_mov_long_double_arm_from_arm (rtx *);
-extern const char *output_mov_double_fpa_from_arm (rtx *);
-extern const char *output_mov_double_arm_from_fpa (rtx *);
-extern const char *output_move_double (rtx *);
-extern const char *output_add_immediate (rtx *);
-extern const char *arithmetic_instr (rtx, int);
-extern void output_ascii_pseudo_op (FILE *, const unsigned char *, int);
-extern const char *output_return_instruction (rtx, int, int);
-extern void arm_poke_function_name (FILE *, const char *);
-extern void arm_print_operand (FILE *, rtx, int);
-extern void arm_print_operand_address (FILE *, rtx);
-extern void arm_final_prescan_insn (rtx);
-extern int arm_go_if_legitimate_address (enum machine_mode, rtx);
-extern int arm_debugger_arg_offset (int, rtx);
-extern int arm_is_longcall_p (rtx, int, int);
-extern int arm_emit_vector_const (FILE *, rtx);
-extern const char * arm_output_load_gr (rtx *);
-extern const char *vfp_output_fstmx (rtx *);
-extern void arm_set_return_address (rtx, rtx);
-extern int arm_eliminable_register (rtx);
-
-extern bool arm_output_addr_const_extra (FILE *, rtx);
-
-#if defined TREE_CODE
-extern rtx arm_function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
-extern void arm_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
-extern bool arm_pad_arg_upward (enum machine_mode, tree);
-extern bool arm_pad_reg_upward (enum machine_mode, tree, int);
-extern bool arm_needs_doubleword_align (enum machine_mode, tree);
-extern rtx arm_function_value(tree, tree);
-#endif
-extern int arm_apply_result_size (void);
-
-#if defined AOF_ASSEMBLER
-extern rtx aof_pic_entry (rtx);
-extern void aof_add_import (const char *);
-extern void aof_delete_import (const char *);
-extern void zero_init_section (void);
-#endif /* AOF_ASSEMBLER */
-
-#endif /* RTX_CODE */
-
-extern int arm_float_words_big_endian (void);
-
-/* Thumb functions. */
-extern void arm_init_expanders (void);
-extern const char *thumb_unexpanded_epilogue (void);
-extern void thumb_expand_prologue (void);
-extern void thumb_expand_epilogue (void);
-#ifdef TREE_CODE
-extern int is_called_in_ARM_mode (tree);
-#endif
-extern int thumb_shiftable_const (unsigned HOST_WIDE_INT);
-#ifdef RTX_CODE
-extern void thumb_final_prescan_insn (rtx);
-extern const char *thumb_load_double_from_address (rtx *);
-extern const char *thumb_output_move_mem_multiple (int, rtx *);
-extern const char *thumb_call_via_reg (rtx);
-extern void thumb_expand_movmemqi (rtx *);
-extern int thumb_go_if_legitimate_address (enum machine_mode, rtx);
-extern rtx arm_return_addr (int, rtx);
-extern void thumb_reload_out_hi (rtx *);
-extern void thumb_reload_in_hi (rtx *);
-extern void thumb_set_return_address (rtx, rtx);
-#endif
-
-/* Defined in pe.c. */
-extern int arm_dllexport_name_p (const char *);
-extern int arm_dllimport_name_p (const char *);
-
-#ifdef TREE_CODE
-extern void arm_pe_unique_section (tree, int);
-extern void arm_pe_encode_section_info (tree, rtx, int);
-extern int arm_dllexport_p (tree);
-extern int arm_dllimport_p (tree);
-extern void arm_mark_dllexport (tree);
-extern void arm_mark_dllimport (tree);
-#endif
-
-extern void arm_pr_long_calls (struct cpp_reader *);
-extern void arm_pr_no_long_calls (struct cpp_reader *);
-extern void arm_pr_long_calls_off (struct cpp_reader *);
-
-#endif /* ! GCC_ARM_PROTOS_H */
diff --git a/gcc-4.2.1/gcc/config/arm/arm-tune.md b/gcc-4.2.1/gcc/config/arm/arm-tune.md
deleted file mode 100644
index 950cd9129..000000000
--- a/gcc-4.2.1/gcc/config/arm/arm-tune.md
+++ /dev/null
@@ -1,5 +0,0 @@
-;; -*- buffer-read-only: t -*-
-;; Generated automatically by gentune.sh from arm-cores.def
-(define_attr "tune"
- "arm2,arm250,arm3,arm6,arm60,arm600,arm610,arm620,arm7,arm7d,arm7di,arm70,arm700,arm700i,arm710,arm720,arm710c,arm7100,arm7500,arm7500fe,arm7m,arm7dm,arm7dmi,arm8,arm810,strongarm,strongarm110,strongarm1100,strongarm1110,arm7tdmi,arm7tdmis,arm710t,arm720t,arm740t,arm9,arm9tdmi,arm920,arm920t,arm922t,arm940t,ep9312,arm10tdmi,arm1020t,arm9e,arm946es,arm966es,arm968es,arm10e,arm1020e,arm1022e,xscale,iwmmxt,arm926ejs,arm1026ejs,arm1136js,arm1136jfs,arm1176jzs,arm1176jzfs,mpcorenovfp,mpcore"
- (const (symbol_ref "arm_tune")))
diff --git a/gcc-4.2.1/gcc/config/arm/arm.c b/gcc-4.2.1/gcc/config/arm/arm.c
deleted file mode 100644
index ec34cb208..000000000
--- a/gcc-4.2.1/gcc/config/arm/arm.c
+++ /dev/null
@@ -1,15651 +0,0 @@
-/* Output routines for GCC for ARM.
- Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
- Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
- and Martin Simmons (@harleqn.co.uk).
- More major hacks by Richard Earnshaw (rearnsha@arm.com).
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "rtl.h"
-#include "tree.h"
-#include "obstack.h"
-#include "regs.h"
-#include "hard-reg-set.h"
-#include "real.h"
-#include "insn-config.h"
-#include "conditions.h"
-#include "output.h"
-#include "insn-attr.h"
-#include "flags.h"
-#include "reload.h"
-#include "function.h"
-#include "expr.h"
-#include "optabs.h"
-#include "toplev.h"
-#include "recog.h"
-#include "ggc.h"
-#include "except.h"
-#include "c-pragma.h"
-#include "integrate.h"
-#include "tm_p.h"
-#include "target.h"
-#include "target-def.h"
-#include "debug.h"
-#include "langhooks.h"
-
-/* Forward definitions of types. */
-typedef struct minipool_node Mnode;
-typedef struct minipool_fixup Mfix;
-
-const struct attribute_spec arm_attribute_table[];
-
-/* Forward function declarations. */
-static arm_stack_offsets *arm_get_frame_offsets (void);
-static void arm_add_gc_roots (void);
-static int arm_gen_constant (enum rtx_code, enum machine_mode, rtx,
- HOST_WIDE_INT, rtx, rtx, int, int);
-static unsigned bit_count (unsigned long);
-static int arm_address_register_rtx_p (rtx, int);
-static int arm_legitimate_index_p (enum machine_mode, rtx, RTX_CODE, int);
-static int thumb_base_register_rtx_p (rtx, enum machine_mode, int);
-inline static int thumb_index_register_rtx_p (rtx, int);
-static int thumb_far_jump_used_p (void);
-static bool thumb_force_lr_save (void);
-static int const_ok_for_op (HOST_WIDE_INT, enum rtx_code);
-static rtx emit_sfm (int, int);
-static int arm_size_return_regs (void);
-#ifndef AOF_ASSEMBLER
-static bool arm_assemble_integer (rtx, unsigned int, int);
-#endif
-static const char *fp_const_from_val (REAL_VALUE_TYPE *);
-static arm_cc get_arm_condition_code (rtx);
-static HOST_WIDE_INT int_log2 (HOST_WIDE_INT);
-static rtx is_jump_table (rtx);
-static const char *output_multi_immediate (rtx *, const char *, const char *,
- int, HOST_WIDE_INT);
-static const char *shift_op (rtx, HOST_WIDE_INT *);
-static struct machine_function *arm_init_machine_status (void);
-static void thumb_exit (FILE *, int);
-static rtx is_jump_table (rtx);
-static HOST_WIDE_INT get_jump_table_size (rtx);
-static Mnode *move_minipool_fix_forward_ref (Mnode *, Mnode *, HOST_WIDE_INT);
-static Mnode *add_minipool_forward_ref (Mfix *);
-static Mnode *move_minipool_fix_backward_ref (Mnode *, Mnode *, HOST_WIDE_INT);
-static Mnode *add_minipool_backward_ref (Mfix *);
-static void assign_minipool_offsets (Mfix *);
-static void arm_print_value (FILE *, rtx);
-static void dump_minipool (rtx);
-static int arm_barrier_cost (rtx);
-static Mfix *create_fix_barrier (Mfix *, HOST_WIDE_INT);
-static void push_minipool_barrier (rtx, HOST_WIDE_INT);
-static void push_minipool_fix (rtx, HOST_WIDE_INT, rtx *, enum machine_mode,
- rtx);
-static void arm_reorg (void);
-static bool note_invalid_constants (rtx, HOST_WIDE_INT, int);
-static int current_file_function_operand (rtx);
-static unsigned long arm_compute_save_reg0_reg12_mask (void);
-static unsigned long arm_compute_save_reg_mask (void);
-static unsigned long arm_isr_value (tree);
-static unsigned long arm_compute_func_type (void);
-static tree arm_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
-static tree arm_handle_isr_attribute (tree *, tree, tree, int, bool *);
-#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
-static tree arm_handle_notshared_attribute (tree *, tree, tree, int, bool *);
-#endif
-static void arm_output_function_epilogue (FILE *, HOST_WIDE_INT);
-static void arm_output_function_prologue (FILE *, HOST_WIDE_INT);
-static void thumb_output_function_prologue (FILE *, HOST_WIDE_INT);
-static int arm_comp_type_attributes (tree, tree);
-static void arm_set_default_type_attributes (tree);
-static int arm_adjust_cost (rtx, rtx, rtx, int);
-static int count_insns_for_constant (HOST_WIDE_INT, int);
-static int arm_get_strip_length (int);
-static bool arm_function_ok_for_sibcall (tree, tree);
-static void arm_internal_label (FILE *, const char *, unsigned long);
-static void arm_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT,
- tree);
-static int arm_rtx_costs_1 (rtx, enum rtx_code, enum rtx_code);
-static bool arm_size_rtx_costs (rtx, int, int, int *);
-static bool arm_slowmul_rtx_costs (rtx, int, int, int *);
-static bool arm_fastmul_rtx_costs (rtx, int, int, int *);
-static bool arm_xscale_rtx_costs (rtx, int, int, int *);
-static bool arm_9e_rtx_costs (rtx, int, int, int *);
-static int arm_address_cost (rtx);
-static bool arm_memory_load_p (rtx);
-static bool arm_cirrus_insn_p (rtx);
-static void cirrus_reorg (rtx);
-static void arm_init_builtins (void);
-static rtx arm_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
-static void arm_init_iwmmxt_builtins (void);
-static rtx safe_vector_operand (rtx, enum machine_mode);
-static rtx arm_expand_binop_builtin (enum insn_code, tree, rtx);
-static rtx arm_expand_unop_builtin (enum insn_code, tree, rtx, int);
-static rtx arm_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
-static void emit_constant_insn (rtx cond, rtx pattern);
-static rtx emit_set_insn (rtx, rtx);
-static int arm_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
- tree, bool);
-
-#ifdef OBJECT_FORMAT_ELF
-static void arm_elf_asm_constructor (rtx, int);
-#endif
-#ifndef ARM_PE
-static void arm_encode_section_info (tree, rtx, int);
-#endif
-
-static void arm_file_end (void);
-
-#ifdef AOF_ASSEMBLER
-static void aof_globalize_label (FILE *, const char *);
-static void aof_dump_imports (FILE *);
-static void aof_dump_pic_table (FILE *);
-static void aof_file_start (void);
-static void aof_file_end (void);
-static void aof_asm_init_sections (void);
-#endif
-static void arm_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
- tree, int *, int);
-static bool arm_pass_by_reference (CUMULATIVE_ARGS *,
- enum machine_mode, tree, bool);
-static bool arm_promote_prototypes (tree);
-static bool arm_default_short_enums (void);
-static bool arm_align_anon_bitfield (void);
-static bool arm_return_in_msb (tree);
-static bool arm_must_pass_in_stack (enum machine_mode, tree);
-#ifdef TARGET_UNWIND_INFO
-static void arm_unwind_emit (FILE *, rtx);
-static bool arm_output_ttype (rtx);
-#endif
-
-static tree arm_cxx_guard_type (void);
-static bool arm_cxx_guard_mask_bit (void);
-static tree arm_get_cookie_size (tree);
-static bool arm_cookie_has_size (void);
-static bool arm_cxx_cdtor_returns_this (void);
-static bool arm_cxx_key_method_may_be_inline (void);
-static void arm_cxx_determine_class_data_visibility (tree);
-static bool arm_cxx_class_data_always_comdat (void);
-static bool arm_cxx_use_aeabi_atexit (void);
-static void arm_init_libfuncs (void);
-static bool arm_handle_option (size_t, const char *, int);
-static unsigned HOST_WIDE_INT arm_shift_truncation_mask (enum machine_mode);
-static bool arm_cannot_copy_insn_p (rtx);
-static bool arm_tls_symbol_p (rtx x);
-
-
-/* Initialize the GCC target structure. */
-#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
-#undef TARGET_MERGE_DECL_ATTRIBUTES
-#define TARGET_MERGE_DECL_ATTRIBUTES merge_dllimport_decl_attributes
-#endif
-
-#undef TARGET_ATTRIBUTE_TABLE
-#define TARGET_ATTRIBUTE_TABLE arm_attribute_table
-
-#undef TARGET_ASM_FILE_END
-#define TARGET_ASM_FILE_END arm_file_end
-
-#ifdef AOF_ASSEMBLER
-#undef TARGET_ASM_BYTE_OP
-#define TARGET_ASM_BYTE_OP "\tDCB\t"
-#undef TARGET_ASM_ALIGNED_HI_OP
-#define TARGET_ASM_ALIGNED_HI_OP "\tDCW\t"
-#undef TARGET_ASM_ALIGNED_SI_OP
-#define TARGET_ASM_ALIGNED_SI_OP "\tDCD\t"
-#undef TARGET_ASM_GLOBALIZE_LABEL
-#define TARGET_ASM_GLOBALIZE_LABEL aof_globalize_label
-#undef TARGET_ASM_FILE_START
-#define TARGET_ASM_FILE_START aof_file_start
-#undef TARGET_ASM_FILE_END
-#define TARGET_ASM_FILE_END aof_file_end
-#else
-#undef TARGET_ASM_ALIGNED_SI_OP
-#define TARGET_ASM_ALIGNED_SI_OP NULL
-#undef TARGET_ASM_INTEGER
-#define TARGET_ASM_INTEGER arm_assemble_integer
-#endif
-
-#undef TARGET_ASM_FUNCTION_PROLOGUE
-#define TARGET_ASM_FUNCTION_PROLOGUE arm_output_function_prologue
-
-#undef TARGET_ASM_FUNCTION_EPILOGUE
-#define TARGET_ASM_FUNCTION_EPILOGUE arm_output_function_epilogue
-
-#undef TARGET_DEFAULT_TARGET_FLAGS
-#define TARGET_DEFAULT_TARGET_FLAGS (TARGET_DEFAULT | MASK_SCHED_PROLOG)
-#undef TARGET_HANDLE_OPTION
-#define TARGET_HANDLE_OPTION arm_handle_option
-
-#undef TARGET_COMP_TYPE_ATTRIBUTES
-#define TARGET_COMP_TYPE_ATTRIBUTES arm_comp_type_attributes
-
-#undef TARGET_SET_DEFAULT_TYPE_ATTRIBUTES
-#define TARGET_SET_DEFAULT_TYPE_ATTRIBUTES arm_set_default_type_attributes
-
-#undef TARGET_SCHED_ADJUST_COST
-#define TARGET_SCHED_ADJUST_COST arm_adjust_cost
-
-#undef TARGET_ENCODE_SECTION_INFO
-#ifdef ARM_PE
-#define TARGET_ENCODE_SECTION_INFO arm_pe_encode_section_info
-#else
-#define TARGET_ENCODE_SECTION_INFO arm_encode_section_info
-#endif
-
-#undef TARGET_STRIP_NAME_ENCODING
-#define TARGET_STRIP_NAME_ENCODING arm_strip_name_encoding
-
-#undef TARGET_ASM_INTERNAL_LABEL
-#define TARGET_ASM_INTERNAL_LABEL arm_internal_label
-
-#undef TARGET_FUNCTION_OK_FOR_SIBCALL
-#define TARGET_FUNCTION_OK_FOR_SIBCALL arm_function_ok_for_sibcall
-
-#undef TARGET_ASM_OUTPUT_MI_THUNK
-#define TARGET_ASM_OUTPUT_MI_THUNK arm_output_mi_thunk
-#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
-#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
-
-/* This will be overridden in arm_override_options. */
-#undef TARGET_RTX_COSTS
-#define TARGET_RTX_COSTS arm_slowmul_rtx_costs
-#undef TARGET_ADDRESS_COST
-#define TARGET_ADDRESS_COST arm_address_cost
-
-#undef TARGET_SHIFT_TRUNCATION_MASK
-#define TARGET_SHIFT_TRUNCATION_MASK arm_shift_truncation_mask
-#undef TARGET_VECTOR_MODE_SUPPORTED_P
-#define TARGET_VECTOR_MODE_SUPPORTED_P arm_vector_mode_supported_p
-
-#undef TARGET_MACHINE_DEPENDENT_REORG
-#define TARGET_MACHINE_DEPENDENT_REORG arm_reorg
-
-#undef TARGET_INIT_BUILTINS
-#define TARGET_INIT_BUILTINS arm_init_builtins
-#undef TARGET_EXPAND_BUILTIN
-#define TARGET_EXPAND_BUILTIN arm_expand_builtin
-
-#undef TARGET_INIT_LIBFUNCS
-#define TARGET_INIT_LIBFUNCS arm_init_libfuncs
-
-#undef TARGET_PROMOTE_FUNCTION_ARGS
-#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
-#undef TARGET_PROMOTE_FUNCTION_RETURN
-#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
-#undef TARGET_PROMOTE_PROTOTYPES
-#define TARGET_PROMOTE_PROTOTYPES arm_promote_prototypes
-#undef TARGET_PASS_BY_REFERENCE
-#define TARGET_PASS_BY_REFERENCE arm_pass_by_reference
-#undef TARGET_ARG_PARTIAL_BYTES
-#define TARGET_ARG_PARTIAL_BYTES arm_arg_partial_bytes
-
-#undef TARGET_SETUP_INCOMING_VARARGS
-#define TARGET_SETUP_INCOMING_VARARGS arm_setup_incoming_varargs
-
-#undef TARGET_DEFAULT_SHORT_ENUMS
-#define TARGET_DEFAULT_SHORT_ENUMS arm_default_short_enums
-
-#undef TARGET_ALIGN_ANON_BITFIELD
-#define TARGET_ALIGN_ANON_BITFIELD arm_align_anon_bitfield
-
-#undef TARGET_NARROW_VOLATILE_BITFIELD
-#define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false
-
-#undef TARGET_CXX_GUARD_TYPE
-#define TARGET_CXX_GUARD_TYPE arm_cxx_guard_type
-
-#undef TARGET_CXX_GUARD_MASK_BIT
-#define TARGET_CXX_GUARD_MASK_BIT arm_cxx_guard_mask_bit
-
-#undef TARGET_CXX_GET_COOKIE_SIZE
-#define TARGET_CXX_GET_COOKIE_SIZE arm_get_cookie_size
-
-#undef TARGET_CXX_COOKIE_HAS_SIZE
-#define TARGET_CXX_COOKIE_HAS_SIZE arm_cookie_has_size
-
-#undef TARGET_CXX_CDTOR_RETURNS_THIS
-#define TARGET_CXX_CDTOR_RETURNS_THIS arm_cxx_cdtor_returns_this
-
-#undef TARGET_CXX_KEY_METHOD_MAY_BE_INLINE
-#define TARGET_CXX_KEY_METHOD_MAY_BE_INLINE arm_cxx_key_method_may_be_inline
-
-#undef TARGET_CXX_USE_AEABI_ATEXIT
-#define TARGET_CXX_USE_AEABI_ATEXIT arm_cxx_use_aeabi_atexit
-
-#undef TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY
-#define TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY \
- arm_cxx_determine_class_data_visibility
-
-#undef TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT
-#define TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT arm_cxx_class_data_always_comdat
-
-#undef TARGET_RETURN_IN_MSB
-#define TARGET_RETURN_IN_MSB arm_return_in_msb
-
-#undef TARGET_MUST_PASS_IN_STACK
-#define TARGET_MUST_PASS_IN_STACK arm_must_pass_in_stack
-
-#ifdef TARGET_UNWIND_INFO
-#undef TARGET_UNWIND_EMIT
-#define TARGET_UNWIND_EMIT arm_unwind_emit
-
-/* EABI unwinding tables use a different format for the typeinfo tables. */
-#undef TARGET_ASM_TTYPE
-#define TARGET_ASM_TTYPE arm_output_ttype
-
-#undef TARGET_ARM_EABI_UNWINDER
-#define TARGET_ARM_EABI_UNWINDER true
-#endif /* TARGET_UNWIND_INFO */
-
-#undef TARGET_CANNOT_COPY_INSN_P
-#define TARGET_CANNOT_COPY_INSN_P arm_cannot_copy_insn_p
-
-#ifdef HAVE_AS_TLS
-#undef TARGET_HAVE_TLS
-#define TARGET_HAVE_TLS true
-#endif
-
-#undef TARGET_CANNOT_FORCE_CONST_MEM
-#define TARGET_CANNOT_FORCE_CONST_MEM arm_tls_referenced_p
-
-struct gcc_target targetm = TARGET_INITIALIZER;
-
-/* Obstack for minipool constant handling. */
-static struct obstack minipool_obstack;
-static char * minipool_startobj;
-
-/* The maximum number of insns skipped which
- will be conditionalised if possible. */
-static int max_insns_skipped = 5;
-
-extern FILE * asm_out_file;
-
-/* True if we are currently building a constant table. */
-int making_const_table;
-
-/* Define the information needed to generate branch insns. This is
- stored from the compare operation. */
-rtx arm_compare_op0, arm_compare_op1;
-
-/* The processor for which instructions should be scheduled. */
-enum processor_type arm_tune = arm_none;
-
-/* Which floating point model to use. */
-enum arm_fp_model arm_fp_model;
-
-/* Which floating point hardware is available. */
-enum fputype arm_fpu_arch;
-
-/* Which floating point hardware to schedule for. */
-enum fputype arm_fpu_tune;
-
-/* Whether to use floating point hardware. */
-enum float_abi_type arm_float_abi;
-
-/* Which ABI to use. */
-enum arm_abi_type arm_abi;
-
-/* Which thread pointer model to use. */
-enum arm_tp_type target_thread_pointer = TP_AUTO;
-
-/* Used to parse -mstructure_size_boundary command line option. */
-int arm_structure_size_boundary = DEFAULT_STRUCTURE_SIZE_BOUNDARY;
-
-/* Used for Thumb call_via trampolines. */
-rtx thumb_call_via_label[14];
-static int thumb_call_reg_needed;
-
-/* Bit values used to identify processor capabilities. */
-#define FL_CO_PROC (1 << 0) /* Has external co-processor bus */
-#define FL_ARCH3M (1 << 1) /* Extended multiply */
-#define FL_MODE26 (1 << 2) /* 26-bit mode support */
-#define FL_MODE32 (1 << 3) /* 32-bit mode support */
-#define FL_ARCH4 (1 << 4) /* Architecture rel 4 */
-#define FL_ARCH5 (1 << 5) /* Architecture rel 5 */
-#define FL_THUMB (1 << 6) /* Thumb aware */
-#define FL_LDSCHED (1 << 7) /* Load scheduling necessary */
-#define FL_STRONG (1 << 8) /* StrongARM */
-#define FL_ARCH5E (1 << 9) /* DSP extensions to v5 */
-#define FL_XSCALE (1 << 10) /* XScale */
-#define FL_CIRRUS (1 << 11) /* Cirrus/DSP. */
-#define FL_ARCH6 (1 << 12) /* Architecture rel 6. Adds
- media instructions. */
-#define FL_VFPV2 (1 << 13) /* Vector Floating Point V2. */
-#define FL_WBUF (1 << 14) /* Schedule for write buffer ops.
- Note: ARM6 & 7 derivatives only. */
-#define FL_ARCH6K (1 << 15) /* Architecture rel 6 K extensions. */
-
-#define FL_IWMMXT (1 << 29) /* XScale v2 or "Intel Wireless MMX technology". */
-
-#define FL_FOR_ARCH2 0
-#define FL_FOR_ARCH3 FL_MODE32
-#define FL_FOR_ARCH3M (FL_FOR_ARCH3 | FL_ARCH3M)
-#define FL_FOR_ARCH4 (FL_FOR_ARCH3M | FL_ARCH4)
-#define FL_FOR_ARCH4T (FL_FOR_ARCH4 | FL_THUMB)
-#define FL_FOR_ARCH5 (FL_FOR_ARCH4 | FL_ARCH5)
-#define FL_FOR_ARCH5T (FL_FOR_ARCH5 | FL_THUMB)
-#define FL_FOR_ARCH5E (FL_FOR_ARCH5 | FL_ARCH5E)
-#define FL_FOR_ARCH5TE (FL_FOR_ARCH5E | FL_THUMB)
-#define FL_FOR_ARCH5TEJ FL_FOR_ARCH5TE
-#define FL_FOR_ARCH6 (FL_FOR_ARCH5TE | FL_ARCH6)
-#define FL_FOR_ARCH6J FL_FOR_ARCH6
-#define FL_FOR_ARCH6K (FL_FOR_ARCH6 | FL_ARCH6K)
-#define FL_FOR_ARCH6Z FL_FOR_ARCH6
-#define FL_FOR_ARCH6ZK FL_FOR_ARCH6K
-
-/* The bits in this mask specify which
- instructions we are allowed to generate. */
-static unsigned long insn_flags = 0;
-
-/* The bits in this mask specify which instruction scheduling options should
- be used. */
-static unsigned long tune_flags = 0;
-
-/* The following are used in the arm.md file as equivalents to bits
- in the above two flag variables. */
-
-/* Nonzero if this chip supports the ARM Architecture 3M extensions. */
-int arm_arch3m = 0;
-
-/* Nonzero if this chip supports the ARM Architecture 4 extensions. */
-int arm_arch4 = 0;
-
-/* Nonzero if this chip supports the ARM Architecture 4t extensions. */
-int arm_arch4t = 0;
-
-/* Nonzero if this chip supports the ARM Architecture 5 extensions. */
-int arm_arch5 = 0;
-
-/* Nonzero if this chip supports the ARM Architecture 5E extensions. */
-int arm_arch5e = 0;
-
-/* Nonzero if this chip supports the ARM Architecture 6 extensions. */
-int arm_arch6 = 0;
-
-/* Nonzero if this chip supports the ARM 6K extensions. */
-int arm_arch6k = 0;
-
-/* Nonzero if this chip can benefit from load scheduling. */
-int arm_ld_sched = 0;
-
-/* Nonzero if this chip is a StrongARM. */
-int arm_tune_strongarm = 0;
-
-/* Nonzero if this chip is a Cirrus variant. */
-int arm_arch_cirrus = 0;
-
-/* Nonzero if this chip supports Intel Wireless MMX technology. */
-int arm_arch_iwmmxt = 0;
-
-/* Nonzero if this chip is an XScale. */
-int arm_arch_xscale = 0;
-
-/* Nonzero if tuning for XScale */
-int arm_tune_xscale = 0;
-
-/* Nonzero if we want to tune for stores that access the write-buffer.
- This typically means an ARM6 or ARM7 with MMU or MPU. */
-int arm_tune_wbuf = 0;
-
-/* Nonzero if generating Thumb instructions. */
-int thumb_code = 0;
-
-/* Nonzero if we should define __THUMB_INTERWORK__ in the
- preprocessor.
- XXX This is a bit of a hack, it's intended to help work around
- problems in GLD which doesn't understand that armv5t code is
- interworking clean. */
-int arm_cpp_interwork = 0;
-
-/* In case of a PRE_INC, POST_INC, PRE_DEC, POST_DEC memory reference, we
- must report the mode of the memory reference from PRINT_OPERAND to
- PRINT_OPERAND_ADDRESS. */
-enum machine_mode output_memory_reference_mode;
-
-/* The register number to be used for the PIC offset register. */
-unsigned arm_pic_register = INVALID_REGNUM;
-
-/* Set to 1 when a return insn is output, this means that the epilogue
- is not needed. */
-int return_used_this_function;
-
-/* Set to 1 after arm_reorg has started. Reset to start at the start of
- the next function. */
-static int after_arm_reorg = 0;
-
-/* The maximum number of insns to be used when loading a constant. */
-static int arm_constant_limit = 3;
-
-/* For an explanation of these variables, see final_prescan_insn below. */
-int arm_ccfsm_state;
-enum arm_cond_code arm_current_cc;
-rtx arm_target_insn;
-int arm_target_label;
-
-/* The condition codes of the ARM, and the inverse function. */
-static const char * const arm_condition_codes[] =
-{
- "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
- "hi", "ls", "ge", "lt", "gt", "le", "al", "nv"
-};
-
-#define streq(string1, string2) (strcmp (string1, string2) == 0)
-
-/* Initialization code. */
-
-struct processors
-{
- const char *const name;
- enum processor_type core;
- const char *arch;
- const unsigned long flags;
- bool (* rtx_costs) (rtx, int, int, int *);
-};
-
-/* Not all of these give usefully different compilation alternatives,
- but there is no simple way of generalizing them. */
-static const struct processors all_cores[] =
-{
- /* ARM Cores */
-#define ARM_CORE(NAME, IDENT, ARCH, FLAGS, COSTS) \
- {NAME, arm_none, #ARCH, FLAGS | FL_FOR_ARCH##ARCH, arm_##COSTS##_rtx_costs},
-#include "arm-cores.def"
-#undef ARM_CORE
- {NULL, arm_none, NULL, 0, NULL}
-};
-
-static const struct processors all_architectures[] =
-{
- /* ARM Architectures */
- /* We don't specify rtx_costs here as it will be figured out
- from the core. */
-
- {"armv2", arm2, "2", FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH2, NULL},
- {"armv2a", arm2, "2", FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH2, NULL},
- {"armv3", arm6, "3", FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH3, NULL},
- {"armv3m", arm7m, "3M", FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH3M, NULL},
- {"armv4", arm7tdmi, "4", FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH4, NULL},
- /* Strictly, FL_MODE26 is a permitted option for v4t, but there are no
- implementations that support it, so we will leave it out for now. */
- {"armv4t", arm7tdmi, "4T", FL_CO_PROC | FL_FOR_ARCH4T, NULL},
- {"armv5", arm10tdmi, "5", FL_CO_PROC | FL_FOR_ARCH5, NULL},
- {"armv5t", arm10tdmi, "5T", FL_CO_PROC | FL_FOR_ARCH5T, NULL},
- {"armv5e", arm1026ejs, "5E", FL_CO_PROC | FL_FOR_ARCH5E, NULL},
- {"armv5te", arm1026ejs, "5TE", FL_CO_PROC | FL_FOR_ARCH5TE, NULL},
- {"armv6", arm1136js, "6", FL_CO_PROC | FL_FOR_ARCH6, NULL},
- {"armv6j", arm1136js, "6J", FL_CO_PROC | FL_FOR_ARCH6J, NULL},
- {"armv6k", mpcore, "6K", FL_CO_PROC | FL_FOR_ARCH6K, NULL},
- {"armv6z", arm1176jzs, "6Z", FL_CO_PROC | FL_FOR_ARCH6Z, NULL},
- {"armv6zk", arm1176jzs, "6ZK", FL_CO_PROC | FL_FOR_ARCH6ZK, NULL},
- {"ep9312", ep9312, "4T", FL_LDSCHED | FL_CIRRUS | FL_FOR_ARCH4, NULL},
- {"iwmmxt", iwmmxt, "5TE", FL_LDSCHED | FL_STRONG | FL_FOR_ARCH5TE | FL_XSCALE | FL_IWMMXT , NULL},
- {NULL, arm_none, NULL, 0 , NULL}
-};
-
-struct arm_cpu_select
-{
- const char * string;
- const char * name;
- const struct processors * processors;
-};
-
-/* This is a magic structure. The 'string' field is magically filled in
- with a pointer to the value specified by the user on the command line
- assuming that the user has specified such a value. */
-
-static struct arm_cpu_select arm_select[] =
-{
- /* string name processors */
- { NULL, "-mcpu=", all_cores },
- { NULL, "-march=", all_architectures },
- { NULL, "-mtune=", all_cores }
-};
-
-/* Defines representing the indexes into the above table. */
-#define ARM_OPT_SET_CPU 0
-#define ARM_OPT_SET_ARCH 1
-#define ARM_OPT_SET_TUNE 2
-
-/* The name of the preprocessor macro to define for this architecture. */
-
-char arm_arch_name[] = "__ARM_ARCH_0UNK__";
-
-struct fpu_desc
-{
- const char * name;
- enum fputype fpu;
-};
-
-
-/* Available values for -mfpu=. */
-
-static const struct fpu_desc all_fpus[] =
-{
- {"fpa", FPUTYPE_FPA},
- {"fpe2", FPUTYPE_FPA_EMU2},
- {"fpe3", FPUTYPE_FPA_EMU2},
- {"maverick", FPUTYPE_MAVERICK},
- {"vfp", FPUTYPE_VFP}
-};
-
-
-/* Floating point models used by the different hardware.
- See fputype in arm.h. */
-
-static const enum fputype fp_model_for_fpu[] =
-{
- /* No FP hardware. */
- ARM_FP_MODEL_UNKNOWN, /* FPUTYPE_NONE */
- ARM_FP_MODEL_FPA, /* FPUTYPE_FPA */
- ARM_FP_MODEL_FPA, /* FPUTYPE_FPA_EMU2 */
- ARM_FP_MODEL_FPA, /* FPUTYPE_FPA_EMU3 */
- ARM_FP_MODEL_MAVERICK, /* FPUTYPE_MAVERICK */
- ARM_FP_MODEL_VFP /* FPUTYPE_VFP */
-};
-
-
-struct float_abi
-{
- const char * name;
- enum float_abi_type abi_type;
-};
-
-
-/* Available values for -mfloat-abi=. */
-
-static const struct float_abi all_float_abis[] =
-{
- {"soft", ARM_FLOAT_ABI_SOFT},
- {"softfp", ARM_FLOAT_ABI_SOFTFP},
- {"hard", ARM_FLOAT_ABI_HARD}
-};
-
-
-struct abi_name
-{
- const char *name;
- enum arm_abi_type abi_type;
-};
-
-
-/* Available values for -mabi=. */
-
-static const struct abi_name arm_all_abis[] =
-{
- {"apcs-gnu", ARM_ABI_APCS},
- {"atpcs", ARM_ABI_ATPCS},
- {"aapcs", ARM_ABI_AAPCS},
- {"iwmmxt", ARM_ABI_IWMMXT},
- {"aapcs-linux", ARM_ABI_AAPCS_LINUX}
-};
-
-/* Supported TLS relocations. */
-
-enum tls_reloc {
- TLS_GD32,
- TLS_LDM32,
- TLS_LDO32,
- TLS_IE32,
- TLS_LE32
-};
-
-/* Emit an insn that's a simple single-set. Both the operands must be known
- to be valid. */
-inline static rtx
-emit_set_insn (rtx x, rtx y)
-{
- return emit_insn (gen_rtx_SET (VOIDmode, x, y));
-}
-
-/* Return the number of bits set in VALUE. */
-static unsigned
-bit_count (unsigned long value)
-{
- unsigned long count = 0;
-
- while (value)
- {
- count++;
- value &= value - 1; /* Clear the least-significant set bit. */
- }
-
- return count;
-}
-
-/* Set up library functions unique to ARM. */
-
-static void
-arm_init_libfuncs (void)
-{
- /* There are no special library functions unless we are using the
- ARM BPABI. */
- if (!TARGET_BPABI)
- return;
-
- /* The functions below are described in Section 4 of the "Run-Time
- ABI for the ARM architecture", Version 1.0. */
-
- /* Double-precision floating-point arithmetic. Table 2. */
- set_optab_libfunc (add_optab, DFmode, "__aeabi_dadd");
- set_optab_libfunc (sdiv_optab, DFmode, "__aeabi_ddiv");
- set_optab_libfunc (smul_optab, DFmode, "__aeabi_dmul");
- set_optab_libfunc (neg_optab, DFmode, "__aeabi_dneg");
- set_optab_libfunc (sub_optab, DFmode, "__aeabi_dsub");
-
- /* Double-precision comparisons. Table 3. */
- set_optab_libfunc (eq_optab, DFmode, "__aeabi_dcmpeq");
- set_optab_libfunc (ne_optab, DFmode, NULL);
- set_optab_libfunc (lt_optab, DFmode, "__aeabi_dcmplt");
- set_optab_libfunc (le_optab, DFmode, "__aeabi_dcmple");
- set_optab_libfunc (ge_optab, DFmode, "__aeabi_dcmpge");
- set_optab_libfunc (gt_optab, DFmode, "__aeabi_dcmpgt");
- set_optab_libfunc (unord_optab, DFmode, "__aeabi_dcmpun");
-
- /* Single-precision floating-point arithmetic. Table 4. */
- set_optab_libfunc (add_optab, SFmode, "__aeabi_fadd");
- set_optab_libfunc (sdiv_optab, SFmode, "__aeabi_fdiv");
- set_optab_libfunc (smul_optab, SFmode, "__aeabi_fmul");
- set_optab_libfunc (neg_optab, SFmode, "__aeabi_fneg");
- set_optab_libfunc (sub_optab, SFmode, "__aeabi_fsub");
-
- /* Single-precision comparisons. Table 5. */
- set_optab_libfunc (eq_optab, SFmode, "__aeabi_fcmpeq");
- set_optab_libfunc (ne_optab, SFmode, NULL);
- set_optab_libfunc (lt_optab, SFmode, "__aeabi_fcmplt");
- set_optab_libfunc (le_optab, SFmode, "__aeabi_fcmple");
- set_optab_libfunc (ge_optab, SFmode, "__aeabi_fcmpge");
- set_optab_libfunc (gt_optab, SFmode, "__aeabi_fcmpgt");
- set_optab_libfunc (unord_optab, SFmode, "__aeabi_fcmpun");
-
- /* Floating-point to integer conversions. Table 6. */
- set_conv_libfunc (sfix_optab, SImode, DFmode, "__aeabi_d2iz");
- set_conv_libfunc (ufix_optab, SImode, DFmode, "__aeabi_d2uiz");
- set_conv_libfunc (sfix_optab, DImode, DFmode, "__aeabi_d2lz");
- set_conv_libfunc (ufix_optab, DImode, DFmode, "__aeabi_d2ulz");
- set_conv_libfunc (sfix_optab, SImode, SFmode, "__aeabi_f2iz");
- set_conv_libfunc (ufix_optab, SImode, SFmode, "__aeabi_f2uiz");
- set_conv_libfunc (sfix_optab, DImode, SFmode, "__aeabi_f2lz");
- set_conv_libfunc (ufix_optab, DImode, SFmode, "__aeabi_f2ulz");
-
- /* Conversions between floating types. Table 7. */
- set_conv_libfunc (trunc_optab, SFmode, DFmode, "__aeabi_d2f");
- set_conv_libfunc (sext_optab, DFmode, SFmode, "__aeabi_f2d");
-
- /* Integer to floating-point conversions. Table 8. */
- set_conv_libfunc (sfloat_optab, DFmode, SImode, "__aeabi_i2d");
- set_conv_libfunc (ufloat_optab, DFmode, SImode, "__aeabi_ui2d");
- set_conv_libfunc (sfloat_optab, DFmode, DImode, "__aeabi_l2d");
- set_conv_libfunc (ufloat_optab, DFmode, DImode, "__aeabi_ul2d");
- set_conv_libfunc (sfloat_optab, SFmode, SImode, "__aeabi_i2f");
- set_conv_libfunc (ufloat_optab, SFmode, SImode, "__aeabi_ui2f");
- set_conv_libfunc (sfloat_optab, SFmode, DImode, "__aeabi_l2f");
- set_conv_libfunc (ufloat_optab, SFmode, DImode, "__aeabi_ul2f");
-
- /* Long long. Table 9. */
- set_optab_libfunc (smul_optab, DImode, "__aeabi_lmul");
- set_optab_libfunc (sdivmod_optab, DImode, "__aeabi_ldivmod");
- set_optab_libfunc (udivmod_optab, DImode, "__aeabi_uldivmod");
- set_optab_libfunc (ashl_optab, DImode, "__aeabi_llsl");
- set_optab_libfunc (lshr_optab, DImode, "__aeabi_llsr");
- set_optab_libfunc (ashr_optab, DImode, "__aeabi_lasr");
- set_optab_libfunc (cmp_optab, DImode, "__aeabi_lcmp");
- set_optab_libfunc (ucmp_optab, DImode, "__aeabi_ulcmp");
-
- /* Integer (32/32->32) division. \S 4.3.1. */
- set_optab_libfunc (sdivmod_optab, SImode, "__aeabi_idivmod");
- set_optab_libfunc (udivmod_optab, SImode, "__aeabi_uidivmod");
-
- /* The divmod functions are designed so that they can be used for
- plain division, even though they return both the quotient and the
- remainder. The quotient is returned in the usual location (i.e.,
- r0 for SImode, {r0, r1} for DImode), just as would be expected
- for an ordinary division routine. Because the AAPCS calling
- conventions specify that all of { r0, r1, r2, r3 } are
- callee-saved registers, there is no need to tell the compiler
- explicitly that those registers are clobbered by these
- routines. */
- set_optab_libfunc (sdiv_optab, DImode, "__aeabi_ldivmod");
- set_optab_libfunc (udiv_optab, DImode, "__aeabi_uldivmod");
-
- /* For SImode division the ABI provides div-without-mod routines,
- which are faster. */
- set_optab_libfunc (sdiv_optab, SImode, "__aeabi_idiv");
- set_optab_libfunc (udiv_optab, SImode, "__aeabi_uidiv");
-
- /* We don't have mod libcalls. Fortunately gcc knows how to use the
- divmod libcalls instead. */
- set_optab_libfunc (smod_optab, DImode, NULL);
- set_optab_libfunc (umod_optab, DImode, NULL);
- set_optab_libfunc (smod_optab, SImode, NULL);
- set_optab_libfunc (umod_optab, SImode, NULL);
-}
-
-/* Implement TARGET_HANDLE_OPTION. */
-
-static bool
-arm_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
-{
- switch (code)
- {
- case OPT_march_:
- arm_select[1].string = arg;
- return true;
-
- case OPT_mcpu_:
- arm_select[0].string = arg;
- return true;
-
- case OPT_mhard_float:
- target_float_abi_name = "hard";
- return true;
-
- case OPT_msoft_float:
- target_float_abi_name = "soft";
- return true;
-
- case OPT_mtune_:
- arm_select[2].string = arg;
- return true;
-
- default:
- return true;
- }
-}
-
-/* Fix up any incompatible options that the user has specified.
- This has now turned into a maze. */
-void
-arm_override_options (void)
-{
- unsigned i;
- enum processor_type target_arch_cpu = arm_none;
-
- /* Set up the flags based on the cpu/architecture selected by the user. */
- for (i = ARRAY_SIZE (arm_select); i--;)
- {
- struct arm_cpu_select * ptr = arm_select + i;
-
- if (ptr->string != NULL && ptr->string[0] != '\0')
- {
- const struct processors * sel;
-
- for (sel = ptr->processors; sel->name != NULL; sel++)
- if (streq (ptr->string, sel->name))
- {
- /* Set the architecture define. */
- if (i != ARM_OPT_SET_TUNE)
- sprintf (arm_arch_name, "__ARM_ARCH_%s__", sel->arch);
-
- /* Determine the processor core for which we should
- tune code-generation. */
- if (/* -mcpu= is a sensible default. */
- i == ARM_OPT_SET_CPU
- /* -mtune= overrides -mcpu= and -march=. */
- || i == ARM_OPT_SET_TUNE)
- arm_tune = (enum processor_type) (sel - ptr->processors);
-
- /* Remember the CPU associated with this architecture.
- If no other option is used to set the CPU type,
- we'll use this to guess the most suitable tuning
- options. */
- if (i == ARM_OPT_SET_ARCH)
- target_arch_cpu = sel->core;
-
- if (i != ARM_OPT_SET_TUNE)
- {
- /* If we have been given an architecture and a processor
- make sure that they are compatible. We only generate
- a warning though, and we prefer the CPU over the
- architecture. */
- if (insn_flags != 0 && (insn_flags ^ sel->flags))
- warning (0, "switch -mcpu=%s conflicts with -march= switch",
- ptr->string);
-
- insn_flags = sel->flags;
- }
-
- break;
- }
-
- if (sel->name == NULL)
- error ("bad value (%s) for %s switch", ptr->string, ptr->name);
- }
- }
-
- /* Guess the tuning options from the architecture if necessary. */
- if (arm_tune == arm_none)
- arm_tune = target_arch_cpu;
-
- /* If the user did not specify a processor, choose one for them. */
- if (insn_flags == 0)
- {
- const struct processors * sel;
- unsigned int sought;
- enum processor_type cpu;
-
- cpu = TARGET_CPU_DEFAULT;
- if (cpu == arm_none)
- {
-#ifdef SUBTARGET_CPU_DEFAULT
- /* Use the subtarget default CPU if none was specified by
- configure. */
- cpu = SUBTARGET_CPU_DEFAULT;
-#endif
- /* Default to ARM6. */
- if (cpu == arm_none)
- cpu = arm6;
- }
- sel = &all_cores[cpu];
-
- insn_flags = sel->flags;
-
- /* Now check to see if the user has specified some command line
- switch that require certain abilities from the cpu. */
- sought = 0;
-
- if (TARGET_INTERWORK || TARGET_THUMB)
- {
- sought |= (FL_THUMB | FL_MODE32);
-
- /* There are no ARM processors that support both APCS-26 and
- interworking. Therefore we force FL_MODE26 to be removed
- from insn_flags here (if it was set), so that the search
- below will always be able to find a compatible processor. */
- insn_flags &= ~FL_MODE26;
- }
-
- if (sought != 0 && ((sought & insn_flags) != sought))
- {
- /* Try to locate a CPU type that supports all of the abilities
- of the default CPU, plus the extra abilities requested by
- the user. */
- for (sel = all_cores; sel->name != NULL; sel++)
- if ((sel->flags & sought) == (sought | insn_flags))
- break;
-
- if (sel->name == NULL)
- {
- unsigned current_bit_count = 0;
- const struct processors * best_fit = NULL;
-
- /* Ideally we would like to issue an error message here
- saying that it was not possible to find a CPU compatible
- with the default CPU, but which also supports the command
- line options specified by the programmer, and so they
- ought to use the -mcpu=<name> command line option to
- override the default CPU type.
-
- If we cannot find a cpu that has both the
- characteristics of the default cpu and the given
- command line options we scan the array again looking
- for a best match. */
- for (sel = all_cores; sel->name != NULL; sel++)
- if ((sel->flags & sought) == sought)
- {
- unsigned count;
-
- count = bit_count (sel->flags & insn_flags);
-
- if (count >= current_bit_count)
- {
- best_fit = sel;
- current_bit_count = count;
- }
- }
-
- gcc_assert (best_fit);
- sel = best_fit;
- }
-
- insn_flags = sel->flags;
- }
- sprintf (arm_arch_name, "__ARM_ARCH_%s__", sel->arch);
- if (arm_tune == arm_none)
- arm_tune = (enum processor_type) (sel - all_cores);
- }
-
- /* The processor for which we should tune should now have been
- chosen. */
- gcc_assert (arm_tune != arm_none);
-
- tune_flags = all_cores[(int)arm_tune].flags;
- if (optimize_size)
- targetm.rtx_costs = arm_size_rtx_costs;
- else
- targetm.rtx_costs = all_cores[(int)arm_tune].rtx_costs;
-
- /* Make sure that the processor choice does not conflict with any of the
- other command line choices. */
- if (TARGET_INTERWORK && !(insn_flags & FL_THUMB))
- {
- warning (0, "target CPU does not support interworking" );
- target_flags &= ~MASK_INTERWORK;
- }
-
- if (TARGET_THUMB && !(insn_flags & FL_THUMB))
- {
- warning (0, "target CPU does not support THUMB instructions");
- target_flags &= ~MASK_THUMB;
- }
-
- if (TARGET_APCS_FRAME && TARGET_THUMB)
- {
- /* warning (0, "ignoring -mapcs-frame because -mthumb was used"); */
- target_flags &= ~MASK_APCS_FRAME;
- }
-
- /* Callee super interworking implies thumb interworking. Adding
- this to the flags here simplifies the logic elsewhere. */
- if (TARGET_THUMB && TARGET_CALLEE_INTERWORKING)
- target_flags |= MASK_INTERWORK;
-
- /* TARGET_BACKTRACE calls leaf_function_p, which causes a crash if done
- from here where no function is being compiled currently. */
- if ((TARGET_TPCS_FRAME || TARGET_TPCS_LEAF_FRAME) && TARGET_ARM)
- warning (0, "enabling backtrace support is only meaningful when compiling for the Thumb");
-
- if (TARGET_ARM && TARGET_CALLEE_INTERWORKING)
- warning (0, "enabling callee interworking support is only meaningful when compiling for the Thumb");
-
- if (TARGET_ARM && TARGET_CALLER_INTERWORKING)
- warning (0, "enabling caller interworking support is only meaningful when compiling for the Thumb");
-
- if (TARGET_APCS_STACK && !TARGET_APCS_FRAME)
- {
- warning (0, "-mapcs-stack-check incompatible with -mno-apcs-frame");
- target_flags |= MASK_APCS_FRAME;
- }
-
- if (TARGET_POKE_FUNCTION_NAME)
- target_flags |= MASK_APCS_FRAME;
-
- if (TARGET_APCS_REENT && flag_pic)
- error ("-fpic and -mapcs-reent are incompatible");
-
- if (TARGET_APCS_REENT)
- warning (0, "APCS reentrant code not supported. Ignored");
-
- /* If this target is normally configured to use APCS frames, warn if they
- are turned off and debugging is turned on. */
- if (TARGET_ARM
- && write_symbols != NO_DEBUG
- && !TARGET_APCS_FRAME
- && (TARGET_DEFAULT & MASK_APCS_FRAME))
- warning (0, "-g with -mno-apcs-frame may not give sensible debugging");
-
- /* If stack checking is disabled, we can use r10 as the PIC register,
- which keeps r9 available. */
- if (flag_pic && TARGET_SINGLE_PIC_BASE)
- arm_pic_register = TARGET_APCS_STACK ? 9 : 10;
-
- if (TARGET_APCS_FLOAT)
- warning (0, "passing floating point arguments in fp regs not yet supported");
-
- /* Initialize boolean versions of the flags, for use in the arm.md file. */
- arm_arch3m = (insn_flags & FL_ARCH3M) != 0;
- arm_arch4 = (insn_flags & FL_ARCH4) != 0;
- arm_arch4t = arm_arch4 & ((insn_flags & FL_THUMB) != 0);
- arm_arch5 = (insn_flags & FL_ARCH5) != 0;
- arm_arch5e = (insn_flags & FL_ARCH5E) != 0;
- arm_arch6 = (insn_flags & FL_ARCH6) != 0;
- arm_arch6k = (insn_flags & FL_ARCH6K) != 0;
- arm_arch_xscale = (insn_flags & FL_XSCALE) != 0;
- arm_arch_cirrus = (insn_flags & FL_CIRRUS) != 0;
-
- arm_ld_sched = (tune_flags & FL_LDSCHED) != 0;
- arm_tune_strongarm = (tune_flags & FL_STRONG) != 0;
- thumb_code = (TARGET_ARM == 0);
- arm_tune_wbuf = (tune_flags & FL_WBUF) != 0;
- arm_tune_xscale = (tune_flags & FL_XSCALE) != 0;
- arm_arch_iwmmxt = (insn_flags & FL_IWMMXT) != 0;
-
- /* V5 code we generate is completely interworking capable, so we turn off
- TARGET_INTERWORK here to avoid many tests later on. */
-
- /* XXX However, we must pass the right pre-processor defines to CPP
- or GLD can get confused. This is a hack. */
- if (TARGET_INTERWORK)
- arm_cpp_interwork = 1;
-
- if (arm_arch5)
- target_flags &= ~MASK_INTERWORK;
-
- if (target_abi_name)
- {
- for (i = 0; i < ARRAY_SIZE (arm_all_abis); i++)
- {
- if (streq (arm_all_abis[i].name, target_abi_name))
- {
- arm_abi = arm_all_abis[i].abi_type;
- break;
- }
- }
- if (i == ARRAY_SIZE (arm_all_abis))
- error ("invalid ABI option: -mabi=%s", target_abi_name);
- }
- else
- arm_abi = ARM_DEFAULT_ABI;
-
- if (TARGET_IWMMXT && !ARM_DOUBLEWORD_ALIGN)
- error ("iwmmxt requires an AAPCS compatible ABI for proper operation");
-
- if (TARGET_IWMMXT_ABI && !TARGET_IWMMXT)
- error ("iwmmxt abi requires an iwmmxt capable cpu");
-
- arm_fp_model = ARM_FP_MODEL_UNKNOWN;
- if (target_fpu_name == NULL && target_fpe_name != NULL)
- {
- if (streq (target_fpe_name, "2"))
- target_fpu_name = "fpe2";
- else if (streq (target_fpe_name, "3"))
- target_fpu_name = "fpe3";
- else
- error ("invalid floating point emulation option: -mfpe=%s",
- target_fpe_name);
- }
- if (target_fpu_name != NULL)
- {
- /* The user specified a FPU. */
- for (i = 0; i < ARRAY_SIZE (all_fpus); i++)
- {
- if (streq (all_fpus[i].name, target_fpu_name))
- {
- arm_fpu_arch = all_fpus[i].fpu;
- arm_fpu_tune = arm_fpu_arch;
- arm_fp_model = fp_model_for_fpu[arm_fpu_arch];
- break;
- }
- }
- if (arm_fp_model == ARM_FP_MODEL_UNKNOWN)
- error ("invalid floating point option: -mfpu=%s", target_fpu_name);
- }
- else
- {
-#ifdef FPUTYPE_DEFAULT
- /* Use the default if it is specified for this platform. */
- arm_fpu_arch = FPUTYPE_DEFAULT;
- arm_fpu_tune = FPUTYPE_DEFAULT;
-#else
- /* Pick one based on CPU type. */
- /* ??? Some targets assume FPA is the default.
- if ((insn_flags & FL_VFP) != 0)
- arm_fpu_arch = FPUTYPE_VFP;
- else
- */
- if (arm_arch_cirrus)
- arm_fpu_arch = FPUTYPE_MAVERICK;
- else
- arm_fpu_arch = FPUTYPE_FPA_EMU2;
-#endif
- if (tune_flags & FL_CO_PROC && arm_fpu_arch == FPUTYPE_FPA_EMU2)
- arm_fpu_tune = FPUTYPE_FPA;
- else
- arm_fpu_tune = arm_fpu_arch;
- arm_fp_model = fp_model_for_fpu[arm_fpu_arch];
- gcc_assert (arm_fp_model != ARM_FP_MODEL_UNKNOWN);
- }
-
- if (target_float_abi_name != NULL)
- {
- /* The user specified a FP ABI. */
- for (i = 0; i < ARRAY_SIZE (all_float_abis); i++)
- {
- if (streq (all_float_abis[i].name, target_float_abi_name))
- {
- arm_float_abi = all_float_abis[i].abi_type;
- break;
- }
- }
- if (i == ARRAY_SIZE (all_float_abis))
- error ("invalid floating point abi: -mfloat-abi=%s",
- target_float_abi_name);
- }
- else
- arm_float_abi = TARGET_DEFAULT_FLOAT_ABI;
-
- if (arm_float_abi == ARM_FLOAT_ABI_HARD && TARGET_VFP)
- sorry ("-mfloat-abi=hard and VFP");
-
- /* FPA and iWMMXt are incompatible because the insn encodings overlap.
- VFP and iWMMXt can theoretically coexist, but it's unlikely such silicon
- will ever exist. GCC makes no attempt to support this combination. */
- if (TARGET_IWMMXT && !TARGET_SOFT_FLOAT)
- sorry ("iWMMXt and hardware floating point");
-
- /* If soft-float is specified then don't use FPU. */
- if (TARGET_SOFT_FLOAT)
- arm_fpu_arch = FPUTYPE_NONE;
-
- /* For arm2/3 there is no need to do any scheduling if there is only
- a floating point emulator, or we are doing software floating-point. */
- if ((TARGET_SOFT_FLOAT
- || arm_fpu_tune == FPUTYPE_FPA_EMU2
- || arm_fpu_tune == FPUTYPE_FPA_EMU3)
- && (tune_flags & FL_MODE32) == 0)
- flag_schedule_insns = flag_schedule_insns_after_reload = 0;
-
- if (target_thread_switch)
- {
- if (strcmp (target_thread_switch, "soft") == 0)
- target_thread_pointer = TP_SOFT;
- else if (strcmp (target_thread_switch, "auto") == 0)
- target_thread_pointer = TP_AUTO;
- else if (strcmp (target_thread_switch, "cp15") == 0)
- target_thread_pointer = TP_CP15;
- else
- error ("invalid thread pointer option: -mtp=%s", target_thread_switch);
- }
-
- /* Use the cp15 method if it is available. */
- if (target_thread_pointer == TP_AUTO)
- {
- if (arm_arch6k && !TARGET_THUMB)
- target_thread_pointer = TP_CP15;
- else
- target_thread_pointer = TP_SOFT;
- }
-
- if (TARGET_HARD_TP && TARGET_THUMB)
- error ("can not use -mtp=cp15 with -mthumb");
-
- /* Override the default structure alignment for AAPCS ABI. */
- if (TARGET_AAPCS_BASED)
- arm_structure_size_boundary = 8;
-
- if (structure_size_string != NULL)
- {
- int size = strtol (structure_size_string, NULL, 0);
-
- if (size == 8 || size == 32
- || (ARM_DOUBLEWORD_ALIGN && size == 64))
- arm_structure_size_boundary = size;
- else
- warning (0, "structure size boundary can only be set to %s",
- ARM_DOUBLEWORD_ALIGN ? "8, 32 or 64": "8 or 32");
- }
-
- if (arm_pic_register_string != NULL)
- {
- int pic_register = decode_reg_name (arm_pic_register_string);
-
- if (!flag_pic)
- warning (0, "-mpic-register= is useless without -fpic");
-
- /* Prevent the user from choosing an obviously stupid PIC register. */
- else if (pic_register < 0 || call_used_regs[pic_register]
- || pic_register == HARD_FRAME_POINTER_REGNUM
- || pic_register == STACK_POINTER_REGNUM
- || pic_register >= PC_REGNUM)
- error ("unable to use '%s' for PIC register", arm_pic_register_string);
- else
- arm_pic_register = pic_register;
- }
-
- if (TARGET_THUMB && flag_schedule_insns)
- {
- /* Don't warn since it's on by default in -O2. */
- flag_schedule_insns = 0;
- }
-
- if (optimize_size)
- {
- arm_constant_limit = 1;
-
- /* If optimizing for size, bump the number of instructions that we
- are prepared to conditionally execute (even on a StrongARM). */
- max_insns_skipped = 6;
- }
- else
- {
- /* For processors with load scheduling, it never costs more than
- 2 cycles to load a constant, and the load scheduler may well
- reduce that to 1. */
- if (arm_ld_sched)
- arm_constant_limit = 1;
-
- /* On XScale the longer latency of a load makes it more difficult
- to achieve a good schedule, so it's faster to synthesize
- constants that can be done in two insns. */
- if (arm_tune_xscale)
- arm_constant_limit = 2;
-
- /* StrongARM has early execution of branches, so a sequence
- that is worth skipping is shorter. */
- if (arm_tune_strongarm)
- max_insns_skipped = 3;
- }
-
- /* Register global variables with the garbage collector. */
- arm_add_gc_roots ();
-}
-
-static void
-arm_add_gc_roots (void)
-{
- gcc_obstack_init(&minipool_obstack);
- minipool_startobj = (char *) obstack_alloc (&minipool_obstack, 0);
-}
-
-/* A table of known ARM exception types.
- For use with the interrupt function attribute. */
-
-typedef struct
-{
- const char *const arg;
- const unsigned long return_value;
-}
-isr_attribute_arg;
-
-static const isr_attribute_arg isr_attribute_args [] =
-{
- { "IRQ", ARM_FT_ISR },
- { "irq", ARM_FT_ISR },
- { "FIQ", ARM_FT_FIQ },
- { "fiq", ARM_FT_FIQ },
- { "ABORT", ARM_FT_ISR },
- { "abort", ARM_FT_ISR },
- { "ABORT", ARM_FT_ISR },
- { "abort", ARM_FT_ISR },
- { "UNDEF", ARM_FT_EXCEPTION },
- { "undef", ARM_FT_EXCEPTION },
- { "SWI", ARM_FT_EXCEPTION },
- { "swi", ARM_FT_EXCEPTION },
- { NULL, ARM_FT_NORMAL }
-};
-
-/* Returns the (interrupt) function type of the current
- function, or ARM_FT_UNKNOWN if the type cannot be determined. */
-
-static unsigned long
-arm_isr_value (tree argument)
-{
- const isr_attribute_arg * ptr;
- const char * arg;
-
- /* No argument - default to IRQ. */
- if (argument == NULL_TREE)
- return ARM_FT_ISR;
-
- /* Get the value of the argument. */
- if (TREE_VALUE (argument) == NULL_TREE
- || TREE_CODE (TREE_VALUE (argument)) != STRING_CST)
- return ARM_FT_UNKNOWN;
-
- arg = TREE_STRING_POINTER (TREE_VALUE (argument));
-
- /* Check it against the list of known arguments. */
- for (ptr = isr_attribute_args; ptr->arg != NULL; ptr++)
- if (streq (arg, ptr->arg))
- return ptr->return_value;
-
- /* An unrecognized interrupt type. */
- return ARM_FT_UNKNOWN;
-}
-
-/* Computes the type of the current function. */
-
-static unsigned long
-arm_compute_func_type (void)
-{
- unsigned long type = ARM_FT_UNKNOWN;
- tree a;
- tree attr;
-
- gcc_assert (TREE_CODE (current_function_decl) == FUNCTION_DECL);
-
- /* Decide if the current function is volatile. Such functions
- never return, and many memory cycles can be saved by not storing
- register values that will never be needed again. This optimization
- was added to speed up context switching in a kernel application. */
- if (optimize > 0
- && (TREE_NOTHROW (current_function_decl)
- || !(flag_unwind_tables
- || (flag_exceptions && !USING_SJLJ_EXCEPTIONS)))
- && TREE_THIS_VOLATILE (current_function_decl))
- type |= ARM_FT_VOLATILE;
-
- if (cfun->static_chain_decl != NULL)
- type |= ARM_FT_NESTED;
-
- attr = DECL_ATTRIBUTES (current_function_decl);
-
- a = lookup_attribute ("naked", attr);
- if (a != NULL_TREE)
- type |= ARM_FT_NAKED;
-
- a = lookup_attribute ("isr", attr);
- if (a == NULL_TREE)
- a = lookup_attribute ("interrupt", attr);
-
- if (a == NULL_TREE)
- type |= TARGET_INTERWORK ? ARM_FT_INTERWORKED : ARM_FT_NORMAL;
- else
- type |= arm_isr_value (TREE_VALUE (a));
-
- return type;
-}
-
-/* Returns the type of the current function. */
-
-unsigned long
-arm_current_func_type (void)
-{
- if (ARM_FUNC_TYPE (cfun->machine->func_type) == ARM_FT_UNKNOWN)
- cfun->machine->func_type = arm_compute_func_type ();
-
- return cfun->machine->func_type;
-}
-
-/* Return 1 if it is possible to return using a single instruction.
- If SIBLING is non-null, this is a test for a return before a sibling
- call. SIBLING is the call insn, so we can examine its register usage. */
-
-int
-use_return_insn (int iscond, rtx sibling)
-{
- int regno;
- unsigned int func_type;
- unsigned long saved_int_regs;
- unsigned HOST_WIDE_INT stack_adjust;
- arm_stack_offsets *offsets;
-
- /* Never use a return instruction before reload has run. */
- if (!reload_completed)
- return 0;
-
- func_type = arm_current_func_type ();
-
- /* Naked functions and volatile functions need special
- consideration. */
- if (func_type & (ARM_FT_VOLATILE | ARM_FT_NAKED))
- return 0;
-
- /* So do interrupt functions that use the frame pointer. */
- if (IS_INTERRUPT (func_type) && frame_pointer_needed)
- return 0;
-
- offsets = arm_get_frame_offsets ();
- stack_adjust = offsets->outgoing_args - offsets->saved_regs;
-
- /* As do variadic functions. */
- if (current_function_pretend_args_size
- || cfun->machine->uses_anonymous_args
- /* Or if the function calls __builtin_eh_return () */
- || current_function_calls_eh_return
- /* Or if the function calls alloca */
- || current_function_calls_alloca
- /* Or if there is a stack adjustment. However, if the stack pointer
- is saved on the stack, we can use a pre-incrementing stack load. */
- || !(stack_adjust == 0 || (frame_pointer_needed && stack_adjust == 4)))
- return 0;
-
- saved_int_regs = arm_compute_save_reg_mask ();
-
- /* Unfortunately, the insn
-
- ldmib sp, {..., sp, ...}
-
- triggers a bug on most SA-110 based devices, such that the stack
- pointer won't be correctly restored if the instruction takes a
- page fault. We work around this problem by popping r3 along with
- the other registers, since that is never slower than executing
- another instruction.
-
- We test for !arm_arch5 here, because code for any architecture
- less than this could potentially be run on one of the buggy
- chips. */
- if (stack_adjust == 4 && !arm_arch5)
- {
- /* Validate that r3 is a call-clobbered register (always true in
- the default abi) ... */
- if (!call_used_regs[3])
- return 0;
-
- /* ... that it isn't being used for a return value ... */
- if (arm_size_return_regs () >= (4 * UNITS_PER_WORD))
- return 0;
-
- /* ... or for a tail-call argument ... */
- if (sibling)
- {
- gcc_assert (GET_CODE (sibling) == CALL_INSN);
-
- if (find_regno_fusage (sibling, USE, 3))
- return 0;
- }
-
- /* ... and that there are no call-saved registers in r0-r2
- (always true in the default ABI). */
- if (saved_int_regs & 0x7)
- return 0;
- }
-
- /* Can't be done if interworking with Thumb, and any registers have been
- stacked. */
- if (TARGET_INTERWORK && saved_int_regs != 0)
- return 0;
-
- /* On StrongARM, conditional returns are expensive if they aren't
- taken and multiple registers have been stacked. */
- if (iscond && arm_tune_strongarm)
- {
- /* Conditional return when just the LR is stored is a simple
- conditional-load instruction, that's not expensive. */
- if (saved_int_regs != 0 && saved_int_regs != (1 << LR_REGNUM))
- return 0;
-
- if (flag_pic
- && arm_pic_register != INVALID_REGNUM
- && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
- return 0;
- }
-
- /* If there are saved registers but the LR isn't saved, then we need
- two instructions for the return. */
- if (saved_int_regs && !(saved_int_regs & (1 << LR_REGNUM)))
- return 0;
-
- /* Can't be done if any of the FPA regs are pushed,
- since this also requires an insn. */
- if (TARGET_HARD_FLOAT && TARGET_FPA)
- for (regno = FIRST_FPA_REGNUM; regno <= LAST_FPA_REGNUM; regno++)
- if (regs_ever_live[regno] && !call_used_regs[regno])
- return 0;
-
- /* Likewise VFP regs. */
- if (TARGET_HARD_FLOAT && TARGET_VFP)
- for (regno = FIRST_VFP_REGNUM; regno <= LAST_VFP_REGNUM; regno++)
- if (regs_ever_live[regno] && !call_used_regs[regno])
- return 0;
-
- if (TARGET_REALLY_IWMMXT)
- for (regno = FIRST_IWMMXT_REGNUM; regno <= LAST_IWMMXT_REGNUM; regno++)
- if (regs_ever_live[regno] && ! call_used_regs [regno])
- return 0;
-
- return 1;
-}
-
-/* Return TRUE if int I is a valid immediate ARM constant. */
-
-int
-const_ok_for_arm (HOST_WIDE_INT i)
-{
- int lowbit;
-
- /* For machines with >32 bit HOST_WIDE_INT, the bits above bit 31 must
- be all zero, or all one. */
- if ((i & ~(unsigned HOST_WIDE_INT) 0xffffffff) != 0
- && ((i & ~(unsigned HOST_WIDE_INT) 0xffffffff)
- != ((~(unsigned HOST_WIDE_INT) 0)
- & ~(unsigned HOST_WIDE_INT) 0xffffffff)))
- return FALSE;
-
- i &= (unsigned HOST_WIDE_INT) 0xffffffff;
-
- /* Fast return for 0 and small values. We must do this for zero, since
- the code below can't handle that one case. */
- if ((i & ~(unsigned HOST_WIDE_INT) 0xff) == 0)
- return TRUE;
-
- /* Get the number of trailing zeros, rounded down to the nearest even
- number. */
- lowbit = (ffs ((int) i) - 1) & ~1;
-
- if ((i & ~(((unsigned HOST_WIDE_INT) 0xff) << lowbit)) == 0)
- return TRUE;
- else if (lowbit <= 4
- && ((i & ~0xc000003f) == 0
- || (i & ~0xf000000f) == 0
- || (i & ~0xfc000003) == 0))
- return TRUE;
-
- return FALSE;
-}
-
-/* Return true if I is a valid constant for the operation CODE. */
-static int
-const_ok_for_op (HOST_WIDE_INT i, enum rtx_code code)
-{
- if (const_ok_for_arm (i))
- return 1;
-
- switch (code)
- {
- case PLUS:
- return const_ok_for_arm (ARM_SIGN_EXTEND (-i));
-
- case MINUS: /* Should only occur with (MINUS I reg) => rsb */
- case XOR:
- case IOR:
- return 0;
-
- case AND:
- return const_ok_for_arm (ARM_SIGN_EXTEND (~i));
-
- default:
- gcc_unreachable ();
- }
-}
-
-/* Emit a sequence of insns to handle a large constant.
- CODE is the code of the operation required, it can be any of SET, PLUS,
- IOR, AND, XOR, MINUS;
- MODE is the mode in which the operation is being performed;
- VAL is the integer to operate on;
- SOURCE is the other operand (a register, or a null-pointer for SET);
- SUBTARGETS means it is safe to create scratch registers if that will
- either produce a simpler sequence, or we will want to cse the values.
- Return value is the number of insns emitted. */
-
-int
-arm_split_constant (enum rtx_code code, enum machine_mode mode, rtx insn,
- HOST_WIDE_INT val, rtx target, rtx source, int subtargets)
-{
- rtx cond;
-
- if (insn && GET_CODE (PATTERN (insn)) == COND_EXEC)
- cond = COND_EXEC_TEST (PATTERN (insn));
- else
- cond = NULL_RTX;
-
- if (subtargets || code == SET
- || (GET_CODE (target) == REG && GET_CODE (source) == REG
- && REGNO (target) != REGNO (source)))
- {
- /* After arm_reorg has been called, we can't fix up expensive
- constants by pushing them into memory so we must synthesize
- them in-line, regardless of the cost. This is only likely to
- be more costly on chips that have load delay slots and we are
- compiling without running the scheduler (so no splitting
- occurred before the final instruction emission).
-
- Ref: gcc -O1 -mcpu=strongarm gcc.c-torture/compile/980506-2.c
- */
- if (!after_arm_reorg
- && !cond
- && (arm_gen_constant (code, mode, NULL_RTX, val, target, source,
- 1, 0)
- > arm_constant_limit + (code != SET)))
- {
- if (code == SET)
- {
- /* Currently SET is the only monadic value for CODE, all
- the rest are diadic. */
- emit_set_insn (target, GEN_INT (val));
- return 1;
- }
- else
- {
- rtx temp = subtargets ? gen_reg_rtx (mode) : target;
-
- emit_set_insn (temp, GEN_INT (val));
- /* For MINUS, the value is subtracted from, since we never
- have subtraction of a constant. */
- if (code == MINUS)
- emit_set_insn (target, gen_rtx_MINUS (mode, temp, source));
- else
- emit_set_insn (target,
- gen_rtx_fmt_ee (code, mode, source, temp));
- return 2;
- }
- }
- }
-
- return arm_gen_constant (code, mode, cond, val, target, source, subtargets,
- 1);
-}
-
-static int
-count_insns_for_constant (HOST_WIDE_INT remainder, int i)
-{
- HOST_WIDE_INT temp1;
- int num_insns = 0;
- do
- {
- int end;
-
- if (i <= 0)
- i += 32;
- if (remainder & (3 << (i - 2)))
- {
- end = i - 8;
- if (end < 0)
- end += 32;
- temp1 = remainder & ((0x0ff << end)
- | ((i < end) ? (0xff >> (32 - end)) : 0));
- remainder &= ~temp1;
- num_insns++;
- i -= 6;
- }
- i -= 2;
- } while (remainder);
- return num_insns;
-}
-
-/* Emit an instruction with the indicated PATTERN. If COND is
- non-NULL, conditionalize the execution of the instruction on COND
- being true. */
-
-static void
-emit_constant_insn (rtx cond, rtx pattern)
-{
- if (cond)
- pattern = gen_rtx_COND_EXEC (VOIDmode, copy_rtx (cond), pattern);
- emit_insn (pattern);
-}
-
-/* As above, but extra parameter GENERATE which, if clear, suppresses
- RTL generation. */
-
-static int
-arm_gen_constant (enum rtx_code code, enum machine_mode mode, rtx cond,
- HOST_WIDE_INT val, rtx target, rtx source, int subtargets,
- int generate)
-{
- int can_invert = 0;
- int can_negate = 0;
- int can_negate_initial = 0;
- int can_shift = 0;
- int i;
- int num_bits_set = 0;
- int set_sign_bit_copies = 0;
- int clear_sign_bit_copies = 0;
- int clear_zero_bit_copies = 0;
- int set_zero_bit_copies = 0;
- int insns = 0;
- unsigned HOST_WIDE_INT temp1, temp2;
- unsigned HOST_WIDE_INT remainder = val & 0xffffffff;
-
- /* Find out which operations are safe for a given CODE. Also do a quick
- check for degenerate cases; these can occur when DImode operations
- are split. */
- switch (code)
- {
- case SET:
- can_invert = 1;
- can_shift = 1;
- can_negate = 1;
- break;
-
- case PLUS:
- can_negate = 1;
- can_negate_initial = 1;
- break;
-
- case IOR:
- if (remainder == 0xffffffff)
- {
- if (generate)
- emit_constant_insn (cond,
- gen_rtx_SET (VOIDmode, target,
- GEN_INT (ARM_SIGN_EXTEND (val))));
- return 1;
- }
- if (remainder == 0)
- {
- if (reload_completed && rtx_equal_p (target, source))
- return 0;
- if (generate)
- emit_constant_insn (cond,
- gen_rtx_SET (VOIDmode, target, source));
- return 1;
- }
- break;
-
- case AND:
- if (remainder == 0)
- {
- if (generate)
- emit_constant_insn (cond,
- gen_rtx_SET (VOIDmode, target, const0_rtx));
- return 1;
- }
- if (remainder == 0xffffffff)
- {
- if (reload_completed && rtx_equal_p (target, source))
- return 0;
- if (generate)
- emit_constant_insn (cond,
- gen_rtx_SET (VOIDmode, target, source));
- return 1;
- }
- can_invert = 1;
- break;
-
- case XOR:
- if (remainder == 0)
- {
- if (reload_completed && rtx_equal_p (target, source))
- return 0;
- if (generate)
- emit_constant_insn (cond,
- gen_rtx_SET (VOIDmode, target, source));
- return 1;
- }
-
- /* We don't know how to handle other cases yet. */
- gcc_assert (remainder == 0xffffffff);
-
- if (generate)
- emit_constant_insn (cond,
- gen_rtx_SET (VOIDmode, target,
- gen_rtx_NOT (mode, source)));
- return 1;
-
- case MINUS:
- /* We treat MINUS as (val - source), since (source - val) is always
- passed as (source + (-val)). */
- if (remainder == 0)
- {
- if (generate)
- emit_constant_insn (cond,
- gen_rtx_SET (VOIDmode, target,
- gen_rtx_NEG (mode, source)));
- return 1;
- }
- if (const_ok_for_arm (val))
- {
- if (generate)
- emit_constant_insn (cond,
- gen_rtx_SET (VOIDmode, target,
- gen_rtx_MINUS (mode, GEN_INT (val),
- source)));
- return 1;
- }
- can_negate = 1;
-
- break;
-
- default:
- gcc_unreachable ();
- }
-
- /* If we can do it in one insn get out quickly. */
- if (const_ok_for_arm (val)
- || (can_negate_initial && const_ok_for_arm (-val))
- || (can_invert && const_ok_for_arm (~val)))
- {
- if (generate)
- emit_constant_insn (cond,
- gen_rtx_SET (VOIDmode, target,
- (source
- ? gen_rtx_fmt_ee (code, mode, source,
- GEN_INT (val))
- : GEN_INT (val))));
- return 1;
- }
-
- /* Calculate a few attributes that may be useful for specific
- optimizations. */
- for (i = 31; i >= 0; i--)
- {
- if ((remainder & (1 << i)) == 0)
- clear_sign_bit_copies++;
- else
- break;
- }
-
- for (i = 31; i >= 0; i--)
- {
- if ((remainder & (1 << i)) != 0)
- set_sign_bit_copies++;
- else
- break;
- }
-
- for (i = 0; i <= 31; i++)
- {
- if ((remainder & (1 << i)) == 0)
- clear_zero_bit_copies++;
- else
- break;
- }
-
- for (i = 0; i <= 31; i++)
- {
- if ((remainder & (1 << i)) != 0)
- set_zero_bit_copies++;
- else
- break;
- }
-
- switch (code)
- {
- case SET:
- /* See if we can do this by sign_extending a constant that is known
- to be negative. This is a good, way of doing it, since the shift
- may well merge into a subsequent insn. */
- if (set_sign_bit_copies > 1)
- {
- if (const_ok_for_arm
- (temp1 = ARM_SIGN_EXTEND (remainder
- << (set_sign_bit_copies - 1))))
- {
- if (generate)
- {
- rtx new_src = subtargets ? gen_reg_rtx (mode) : target;
- emit_constant_insn (cond,
- gen_rtx_SET (VOIDmode, new_src,
- GEN_INT (temp1)));
- emit_constant_insn (cond,
- gen_ashrsi3 (target, new_src,
- GEN_INT (set_sign_bit_copies - 1)));
- }
- return 2;
- }
- /* For an inverted constant, we will need to set the low bits,
- these will be shifted out of harm's way. */
- temp1 |= (1 << (set_sign_bit_copies - 1)) - 1;
- if (const_ok_for_arm (~temp1))
- {
- if (generate)
- {
- rtx new_src = subtargets ? gen_reg_rtx (mode) : target;
- emit_constant_insn (cond,
- gen_rtx_SET (VOIDmode, new_src,
- GEN_INT (temp1)));
- emit_constant_insn (cond,
- gen_ashrsi3 (target, new_src,
- GEN_INT (set_sign_bit_copies - 1)));
- }
- return 2;
- }
- }
-
- /* See if we can calculate the value as the difference between two
- valid immediates. */
- if (clear_sign_bit_copies + clear_zero_bit_copies <= 16)
- {
- int topshift = clear_sign_bit_copies & ~1;
-
- temp1 = ARM_SIGN_EXTEND ((remainder + (0x00800000 >> topshift))
- & (0xff000000 >> topshift));
-
- /* If temp1 is zero, then that means the 9 most significant
- bits of remainder were 1 and we've caused it to overflow.
- When topshift is 0 we don't need to do anything since we
- can borrow from 'bit 32'. */
- if (temp1 == 0 && topshift != 0)
- temp1 = 0x80000000 >> (topshift - 1);
-
- temp2 = ARM_SIGN_EXTEND (temp1 - remainder);
-
- if (const_ok_for_arm (temp2))
- {
- if (generate)
- {
- rtx new_src = subtargets ? gen_reg_rtx (mode) : target;
- emit_constant_insn (cond,
- gen_rtx_SET (VOIDmode, new_src,
- GEN_INT (temp1)));
- emit_constant_insn (cond,
- gen_addsi3 (target, new_src,
- GEN_INT (-temp2)));
- }
-
- return 2;
- }
- }
-
- /* See if we can generate this by setting the bottom (or the top)
- 16 bits, and then shifting these into the other half of the
- word. We only look for the simplest cases, to do more would cost
- too much. Be careful, however, not to generate this when the
- alternative would take fewer insns. */
- if (val & 0xffff0000)
- {
- temp1 = remainder & 0xffff0000;
- temp2 = remainder & 0x0000ffff;
-
- /* Overlaps outside this range are best done using other methods. */
- for (i = 9; i < 24; i++)
- {
- if ((((temp2 | (temp2 << i)) & 0xffffffff) == remainder)
- && !const_ok_for_arm (temp2))
- {
- rtx new_src = (subtargets
- ? (generate ? gen_reg_rtx (mode) : NULL_RTX)
- : target);
- insns = arm_gen_constant (code, mode, cond, temp2, new_src,
- source, subtargets, generate);
- source = new_src;
- if (generate)
- emit_constant_insn
- (cond,
- gen_rtx_SET
- (VOIDmode, target,
- gen_rtx_IOR (mode,
- gen_rtx_ASHIFT (mode, source,
- GEN_INT (i)),
- source)));
- return insns + 1;
- }
- }
-
- /* Don't duplicate cases already considered. */
- for (i = 17; i < 24; i++)
- {
- if (((temp1 | (temp1 >> i)) == remainder)
- && !const_ok_for_arm (temp1))
- {
- rtx new_src = (subtargets
- ? (generate ? gen_reg_rtx (mode) : NULL_RTX)
- : target);
- insns = arm_gen_constant (code, mode, cond, temp1, new_src,
- source, subtargets, generate);
- source = new_src;
- if (generate)
- emit_constant_insn
- (cond,
- gen_rtx_SET (VOIDmode, target,
- gen_rtx_IOR
- (mode,
- gen_rtx_LSHIFTRT (mode, source,
- GEN_INT (i)),
- source)));
- return insns + 1;
- }
- }
- }
- break;
-
- case IOR:
- case XOR:
- /* If we have IOR or XOR, and the constant can be loaded in a
- single instruction, and we can find a temporary to put it in,
- then this can be done in two instructions instead of 3-4. */
- if (subtargets
- /* TARGET can't be NULL if SUBTARGETS is 0 */
- || (reload_completed && !reg_mentioned_p (target, source)))
- {
- if (const_ok_for_arm (ARM_SIGN_EXTEND (~val)))
- {
- if (generate)
- {
- rtx sub = subtargets ? gen_reg_rtx (mode) : target;
-
- emit_constant_insn (cond,
- gen_rtx_SET (VOIDmode, sub,
- GEN_INT (val)));
- emit_constant_insn (cond,
- gen_rtx_SET (VOIDmode, target,
- gen_rtx_fmt_ee (code, mode,
- source, sub)));
- }
- return 2;
- }
- }
-
- if (code == XOR)
- break;
-
- if (set_sign_bit_copies > 8
- && (val & (-1 << (32 - set_sign_bit_copies))) == val)
- {
- if (generate)
- {
- rtx sub = subtargets ? gen_reg_rtx (mode) : target;
- rtx shift = GEN_INT (set_sign_bit_copies);
-
- emit_constant_insn
- (cond,
- gen_rtx_SET (VOIDmode, sub,
- gen_rtx_NOT (mode,
- gen_rtx_ASHIFT (mode,
- source,
- shift))));
- emit_constant_insn
- (cond,
- gen_rtx_SET (VOIDmode, target,
- gen_rtx_NOT (mode,
- gen_rtx_LSHIFTRT (mode, sub,
- shift))));
- }
- return 2;
- }
-
- if (set_zero_bit_copies > 8
- && (remainder & ((1 << set_zero_bit_copies) - 1)) == remainder)
- {
- if (generate)
- {
- rtx sub = subtargets ? gen_reg_rtx (mode) : target;
- rtx shift = GEN_INT (set_zero_bit_copies);
-
- emit_constant_insn
- (cond,
- gen_rtx_SET (VOIDmode, sub,
- gen_rtx_NOT (mode,
- gen_rtx_LSHIFTRT (mode,
- source,
- shift))));
- emit_constant_insn
- (cond,
- gen_rtx_SET (VOIDmode, target,
- gen_rtx_NOT (mode,
- gen_rtx_ASHIFT (mode, sub,
- shift))));
- }
- return 2;
- }
-
- if (const_ok_for_arm (temp1 = ARM_SIGN_EXTEND (~val)))
- {
- if (generate)
- {
- rtx sub = subtargets ? gen_reg_rtx (mode) : target;
- emit_constant_insn (cond,
- gen_rtx_SET (VOIDmode, sub,
- gen_rtx_NOT (mode, source)));
- source = sub;
- if (subtargets)
- sub = gen_reg_rtx (mode);
- emit_constant_insn (cond,
- gen_rtx_SET (VOIDmode, sub,
- gen_rtx_AND (mode, source,
- GEN_INT (temp1))));
- emit_constant_insn (cond,
- gen_rtx_SET (VOIDmode, target,
- gen_rtx_NOT (mode, sub)));
- }
- return 3;
- }
- break;
-
- case AND:
- /* See if two shifts will do 2 or more insn's worth of work. */
- if (clear_sign_bit_copies >= 16 && clear_sign_bit_copies < 24)
- {
- HOST_WIDE_INT shift_mask = ((0xffffffff
- << (32 - clear_sign_bit_copies))
- & 0xffffffff);
-
- if ((remainder | shift_mask) != 0xffffffff)
- {
- if (generate)
- {
- rtx new_src = subtargets ? gen_reg_rtx (mode) : target;
- insns = arm_gen_constant (AND, mode, cond,
- remainder | shift_mask,
- new_src, source, subtargets, 1);
- source = new_src;
- }
- else
- {
- rtx targ = subtargets ? NULL_RTX : target;
- insns = arm_gen_constant (AND, mode, cond,
- remainder | shift_mask,
- targ, source, subtargets, 0);
- }
- }
-
- if (generate)
- {
- rtx new_src = subtargets ? gen_reg_rtx (mode) : target;
- rtx shift = GEN_INT (clear_sign_bit_copies);
-
- emit_insn (gen_ashlsi3 (new_src, source, shift));
- emit_insn (gen_lshrsi3 (target, new_src, shift));
- }
-
- return insns + 2;
- }
-
- if (clear_zero_bit_copies >= 16 && clear_zero_bit_copies < 24)
- {
- HOST_WIDE_INT shift_mask = (1 << clear_zero_bit_copies) - 1;
-
- if ((remainder | shift_mask) != 0xffffffff)
- {
- if (generate)
- {
- rtx new_src = subtargets ? gen_reg_rtx (mode) : target;
-
- insns = arm_gen_constant (AND, mode, cond,
- remainder | shift_mask,
- new_src, source, subtargets, 1);
- source = new_src;
- }
- else
- {
- rtx targ = subtargets ? NULL_RTX : target;
-
- insns = arm_gen_constant (AND, mode, cond,
- remainder | shift_mask,
- targ, source, subtargets, 0);
- }
- }
-
- if (generate)
- {
- rtx new_src = subtargets ? gen_reg_rtx (mode) : target;
- rtx shift = GEN_INT (clear_zero_bit_copies);
-
- emit_insn (gen_lshrsi3 (new_src, source, shift));
- emit_insn (gen_ashlsi3 (target, new_src, shift));
- }
-
- return insns + 2;
- }
-
- break;
-
- default:
- break;
- }
-
- for (i = 0; i < 32; i++)
- if (remainder & (1 << i))
- num_bits_set++;
-
- if (code == AND || (can_invert && num_bits_set > 16))
- remainder = (~remainder) & 0xffffffff;
- else if (code == PLUS && num_bits_set > 16)
- remainder = (-remainder) & 0xffffffff;
- else
- {
- can_invert = 0;
- can_negate = 0;
- }
-
- /* Now try and find a way of doing the job in either two or three
- instructions.
- We start by looking for the largest block of zeros that are aligned on
- a 2-bit boundary, we then fill up the temps, wrapping around to the
- top of the word when we drop off the bottom.
- In the worst case this code should produce no more than four insns. */
- {
- int best_start = 0;
- int best_consecutive_zeros = 0;
-
- for (i = 0; i < 32; i += 2)
- {
- int consecutive_zeros = 0;
-
- if (!(remainder & (3 << i)))
- {
- while ((i < 32) && !(remainder & (3 << i)))
- {
- consecutive_zeros += 2;
- i += 2;
- }
- if (consecutive_zeros > best_consecutive_zeros)
- {
- best_consecutive_zeros = consecutive_zeros;
- best_start = i - consecutive_zeros;
- }
- i -= 2;
- }
- }
-
- /* So long as it won't require any more insns to do so, it's
- desirable to emit a small constant (in bits 0...9) in the last
- insn. This way there is more chance that it can be combined with
- a later addressing insn to form a pre-indexed load or store
- operation. Consider:
-
- *((volatile int *)0xe0000100) = 1;
- *((volatile int *)0xe0000110) = 2;
-
- We want this to wind up as:
-
- mov rA, #0xe0000000
- mov rB, #1
- str rB, [rA, #0x100]
- mov rB, #2
- str rB, [rA, #0x110]
-
- rather than having to synthesize both large constants from scratch.
-
- Therefore, we calculate how many insns would be required to emit
- the constant starting from `best_start', and also starting from
- zero (i.e. with bit 31 first to be output). If `best_start' doesn't
- yield a shorter sequence, we may as well use zero. */
- if (best_start != 0
- && ((((unsigned HOST_WIDE_INT) 1) << best_start) < remainder)
- && (count_insns_for_constant (remainder, 0) <=
- count_insns_for_constant (remainder, best_start)))
- best_start = 0;
-
- /* Now start emitting the insns. */
- i = best_start;
- do
- {
- int end;
-
- if (i <= 0)
- i += 32;
- if (remainder & (3 << (i - 2)))
- {
- end = i - 8;
- if (end < 0)
- end += 32;
- temp1 = remainder & ((0x0ff << end)
- | ((i < end) ? (0xff >> (32 - end)) : 0));
- remainder &= ~temp1;
-
- if (generate)
- {
- rtx new_src, temp1_rtx;
-
- if (code == SET || code == MINUS)
- {
- new_src = (subtargets ? gen_reg_rtx (mode) : target);
- if (can_invert && code != MINUS)
- temp1 = ~temp1;
- }
- else
- {
- if (remainder && subtargets)
- new_src = gen_reg_rtx (mode);
- else
- new_src = target;
- if (can_invert)
- temp1 = ~temp1;
- else if (can_negate)
- temp1 = -temp1;
- }
-
- temp1 = trunc_int_for_mode (temp1, mode);
- temp1_rtx = GEN_INT (temp1);
-
- if (code == SET)
- ;
- else if (code == MINUS)
- temp1_rtx = gen_rtx_MINUS (mode, temp1_rtx, source);
- else
- temp1_rtx = gen_rtx_fmt_ee (code, mode, source, temp1_rtx);
-
- emit_constant_insn (cond,
- gen_rtx_SET (VOIDmode, new_src,
- temp1_rtx));
- source = new_src;
- }
-
- if (code == SET)
- {
- can_invert = 0;
- code = PLUS;
- }
- else if (code == MINUS)
- code = PLUS;
-
- insns++;
- i -= 6;
- }
- i -= 2;
- }
- while (remainder);
- }
-
- return insns;
-}
-
-/* Canonicalize a comparison so that we are more likely to recognize it.
- This can be done for a few constant compares, where we can make the
- immediate value easier to load. */
-
-enum rtx_code
-arm_canonicalize_comparison (enum rtx_code code, enum machine_mode mode,
- rtx * op1)
-{
- unsigned HOST_WIDE_INT i = INTVAL (*op1);
- unsigned HOST_WIDE_INT maxval;
- maxval = (((unsigned HOST_WIDE_INT) 1) << (GET_MODE_BITSIZE(mode) - 1)) - 1;
-
- switch (code)
- {
- case EQ:
- case NE:
- return code;
-
- case GT:
- case LE:
- if (i != maxval
- && (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
- {
- *op1 = GEN_INT (i + 1);
- return code == GT ? GE : LT;
- }
- break;
-
- case GE:
- case LT:
- if (i != ~maxval
- && (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
- {
- *op1 = GEN_INT (i - 1);
- return code == GE ? GT : LE;
- }
- break;
-
- case GTU:
- case LEU:
- if (i != ~((unsigned HOST_WIDE_INT) 0)
- && (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
- {
- *op1 = GEN_INT (i + 1);
- return code == GTU ? GEU : LTU;
- }
- break;
-
- case GEU:
- case LTU:
- if (i != 0
- && (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
- {
- *op1 = GEN_INT (i - 1);
- return code == GEU ? GTU : LEU;
- }
- break;
-
- default:
- gcc_unreachable ();
- }
-
- return code;
-}
-
-
-/* Define how to find the value returned by a function. */
-
-rtx
-arm_function_value(tree type, tree func ATTRIBUTE_UNUSED)
-{
- enum machine_mode mode;
- int unsignedp ATTRIBUTE_UNUSED;
- rtx r ATTRIBUTE_UNUSED;
-
- mode = TYPE_MODE (type);
- /* Promote integer types. */
- if (INTEGRAL_TYPE_P (type))
- PROMOTE_FUNCTION_MODE (mode, unsignedp, type);
-
- /* Promotes small structs returned in a register to full-word size
- for big-endian AAPCS. */
- if (arm_return_in_msb (type))
- {
- HOST_WIDE_INT size = int_size_in_bytes (type);
- if (size % UNITS_PER_WORD != 0)
- {
- size += UNITS_PER_WORD - size % UNITS_PER_WORD;
- mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
- }
- }
-
- return LIBCALL_VALUE(mode);
-}
-
-/* Determine the amount of memory needed to store the possible return
- registers of an untyped call. */
-int
-arm_apply_result_size (void)
-{
- int size = 16;
-
- if (TARGET_ARM)
- {
- if (TARGET_HARD_FLOAT_ABI)
- {
- if (TARGET_FPA)
- size += 12;
- if (TARGET_MAVERICK)
- size += 8;
- }
- if (TARGET_IWMMXT_ABI)
- size += 8;
- }
-
- return size;
-}
-
-/* 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
-arm_return_in_memory (tree type)
-{
- HOST_WIDE_INT size;
-
- if (!AGGREGATE_TYPE_P (type) &&
- (TREE_CODE (type) != VECTOR_TYPE) &&
- !(TARGET_AAPCS_BASED && TREE_CODE (type) == COMPLEX_TYPE))
- /* All simple types are returned in registers.
- For AAPCS, complex types are treated the same as aggregates. */
- return 0;
-
- size = int_size_in_bytes (type);
-
- if (arm_abi != ARM_ABI_APCS)
- {
- /* ATPCS and later return aggregate types in memory only if they are
- larger than a word (or are variable size). */
- return (size < 0 || size > UNITS_PER_WORD);
- }
-
- /* To maximize backwards compatibility with previous versions of gcc,
- return vectors up to 4 words in registers. */
- if (TREE_CODE (type) == VECTOR_TYPE)
- return (size < 0 || size > (4 * UNITS_PER_WORD));
-
- /* For the arm-wince targets we choose to be compatible with Microsoft's
- ARM and Thumb compilers, which always return aggregates in memory. */
-#ifndef ARM_WINCE
- /* All structures/unions bigger than one word are returned in memory.
- Also catch the case where int_size_in_bytes returns -1. In this case
- the aggregate is either huge or of variable size, and in either case
- we will want to return it via memory and not in a register. */
- if (size < 0 || size > UNITS_PER_WORD)
- return 1;
-
- if (TREE_CODE (type) == RECORD_TYPE)
- {
- tree field;
-
- /* For a struct the APCS says that we only return in a register
- if the type is 'integer like' and 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. */
-
- /* Check that the first field is valid for returning in a register. */
-
- /* ... Floats are not allowed */
- if (FLOAT_TYPE_P (TREE_TYPE (field)))
- return 1;
-
- /* ... Aggregates that are not themselves valid for returning in
- a register are not allowed. */
- if (RETURN_IN_MEMORY (TREE_TYPE (field)))
- return 1;
-
- /* Now check the remaining fields, if any. Only bitfields are allowed,
- since they are not addressable. */
- 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;
- }
-
- 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 (FLOAT_TYPE_P (TREE_TYPE (field)))
- return 1;
-
- if (RETURN_IN_MEMORY (TREE_TYPE (field)))
- return 1;
- }
-
- return 0;
- }
-#endif /* not ARM_WINCE */
-
- /* Return all other types in memory. */
- return 1;
-}
-
-/* Indicate whether or not words of a double are in big-endian order. */
-
-int
-arm_float_words_big_endian (void)
-{
- if (TARGET_MAVERICK)
- return 0;
-
- /* For FPA, float words are always big-endian. For VFP, floats words
- follow the memory system mode. */
-
- if (TARGET_FPA)
- {
- return 1;
- }
-
- if (TARGET_VFP)
- return (TARGET_BIG_END ? 1 : 0);
-
- return 1;
-}
-
-/* Initialize a variable CUM of type CUMULATIVE_ARGS
- for a call to a function whose data type is FNTYPE.
- For a library call, FNTYPE is NULL. */
-void
-arm_init_cumulative_args (CUMULATIVE_ARGS *pcum, tree fntype,
- rtx libname ATTRIBUTE_UNUSED,
- tree fndecl ATTRIBUTE_UNUSED)
-{
- /* On the ARM, the offset starts at 0. */
- pcum->nregs = 0;
- pcum->iwmmxt_nregs = 0;
- pcum->can_split = true;
-
- pcum->call_cookie = CALL_NORMAL;
-
- if (TARGET_LONG_CALLS)
- pcum->call_cookie = CALL_LONG;
-
- /* Check for long call/short call attributes. The attributes
- override any command line option. */
- if (fntype)
- {
- if (lookup_attribute ("short_call", TYPE_ATTRIBUTES (fntype)))
- pcum->call_cookie = CALL_SHORT;
- else if (lookup_attribute ("long_call", TYPE_ATTRIBUTES (fntype)))
- pcum->call_cookie = CALL_LONG;
- }
-
- /* Varargs vectors are treated the same as long long.
- named_count avoids having to change the way arm handles 'named' */
- pcum->named_count = 0;
- pcum->nargs = 0;
-
- if (TARGET_REALLY_IWMMXT && fntype)
- {
- tree fn_arg;
-
- for (fn_arg = TYPE_ARG_TYPES (fntype);
- fn_arg;
- fn_arg = TREE_CHAIN (fn_arg))
- pcum->named_count += 1;
-
- if (! pcum->named_count)
- pcum->named_count = INT_MAX;
- }
-}
-
-
-/* Return true if mode/type need doubleword alignment. */
-bool
-arm_needs_doubleword_align (enum machine_mode mode, tree type)
-{
- return (GET_MODE_ALIGNMENT (mode) > PARM_BOUNDARY
- || (type && TYPE_ALIGN (type) > PARM_BOUNDARY));
-}
-
-
-/* Determine where to put an argument to a function.
- Value is zero to push the argument on the stack,
- or a hard register in which to store the argument.
-
- MODE is the argument's machine mode.
- TYPE is the data type of the argument (as a tree).
- This is null for libcalls where that information may
- not be available.
- CUM is a variable of type CUMULATIVE_ARGS which gives info about
- the preceding args and about the function being called.
- NAMED is nonzero if this argument is a named parameter
- (otherwise it is an extra parameter matching an ellipsis). */
-
-rtx
-arm_function_arg (CUMULATIVE_ARGS *pcum, enum machine_mode mode,
- tree type, int named)
-{
- int nregs;
-
- /* Varargs vectors are treated the same as long long.
- named_count avoids having to change the way arm handles 'named' */
- if (TARGET_IWMMXT_ABI
- && arm_vector_mode_supported_p (mode)
- && pcum->named_count > pcum->nargs + 1)
- {
- if (pcum->iwmmxt_nregs <= 9)
- return gen_rtx_REG (mode, pcum->iwmmxt_nregs + FIRST_IWMMXT_REGNUM);
- else
- {
- pcum->can_split = false;
- return NULL_RTX;
- }
- }
-
- /* Put doubleword aligned quantities in even register pairs. */
- if (pcum->nregs & 1
- && ARM_DOUBLEWORD_ALIGN
- && arm_needs_doubleword_align (mode, type))
- pcum->nregs++;
-
- if (mode == VOIDmode)
- /* Compute operand 2 of the call insn. */
- return GEN_INT (pcum->call_cookie);
-
- /* Only allow splitting an arg between regs and memory if all preceding
- args were allocated to regs. For args passed by reference we only count
- the reference pointer. */
- if (pcum->can_split)
- nregs = 1;
- else
- nregs = ARM_NUM_REGS2 (mode, type);
-
- if (!named || pcum->nregs + nregs > NUM_ARG_REGS)
- return NULL_RTX;
-
- return gen_rtx_REG (mode, pcum->nregs);
-}
-
-static int
-arm_arg_partial_bytes (CUMULATIVE_ARGS *pcum, enum machine_mode mode,
- tree type, bool named ATTRIBUTE_UNUSED)
-{
- int nregs = pcum->nregs;
-
- if (arm_vector_mode_supported_p (mode))
- return 0;
-
- if (NUM_ARG_REGS > nregs
- && (NUM_ARG_REGS < nregs + ARM_NUM_REGS2 (mode, type))
- && pcum->can_split)
- return (NUM_ARG_REGS - nregs) * UNITS_PER_WORD;
-
- return 0;
-}
-
-/* Variable sized types are passed by reference. This is a GCC
- extension to the ARM ABI. */
-
-static bool
-arm_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
- enum machine_mode mode ATTRIBUTE_UNUSED,
- tree type, bool named ATTRIBUTE_UNUSED)
-{
- return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
-}
-
-/* Encode the current state of the #pragma [no_]long_calls. */
-typedef enum
-{
- OFF, /* No #pragma [no_]long_calls is in effect. */
- LONG, /* #pragma long_calls is in effect. */
- SHORT /* #pragma no_long_calls is in effect. */
-} arm_pragma_enum;
-
-static arm_pragma_enum arm_pragma_long_calls = OFF;
-
-void
-arm_pr_long_calls (struct cpp_reader * pfile ATTRIBUTE_UNUSED)
-{
- arm_pragma_long_calls = LONG;
-}
-
-void
-arm_pr_no_long_calls (struct cpp_reader * pfile ATTRIBUTE_UNUSED)
-{
- arm_pragma_long_calls = SHORT;
-}
-
-void
-arm_pr_long_calls_off (struct cpp_reader * pfile ATTRIBUTE_UNUSED)
-{
- arm_pragma_long_calls = OFF;
-}
-
-/* Table of machine attributes. */
-const struct attribute_spec arm_attribute_table[] =
-{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
- /* Function calls made to this symbol must be done indirectly, because
- it may lie outside of the 26 bit addressing range of a normal function
- call. */
- { "long_call", 0, 0, false, true, true, NULL },
- /* Whereas these functions are always known to reside within the 26 bit
- addressing range. */
- { "short_call", 0, 0, false, true, true, NULL },
- /* Interrupt Service Routines have special prologue and epilogue requirements. */
- { "isr", 0, 1, false, false, false, arm_handle_isr_attribute },
- { "interrupt", 0, 1, false, false, false, arm_handle_isr_attribute },
- { "naked", 0, 0, true, false, false, arm_handle_fndecl_attribute },
-#ifdef ARM_PE
- /* ARM/PE has three new attributes:
- interfacearm - ?
- dllexport - for exporting a function/variable that will live in a dll
- dllimport - for importing a function/variable from a dll
-
- Microsoft allows multiple declspecs in one __declspec, separating
- them with spaces. We do NOT support this. Instead, use __declspec
- multiple times.
- */
- { "dllimport", 0, 0, true, false, false, NULL },
- { "dllexport", 0, 0, true, false, false, NULL },
- { "interfacearm", 0, 0, true, false, false, arm_handle_fndecl_attribute },
-#elif TARGET_DLLIMPORT_DECL_ATTRIBUTES
- { "dllimport", 0, 0, false, false, false, handle_dll_attribute },
- { "dllexport", 0, 0, false, false, false, handle_dll_attribute },
- { "notshared", 0, 0, false, true, false, arm_handle_notshared_attribute },
-#endif
- { NULL, 0, 0, false, false, false, NULL }
-};
-
-/* Handle an attribute requiring a FUNCTION_DECL;
- arguments as in struct attribute_spec.handler. */
-static tree
-arm_handle_fndecl_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
-{
- if (TREE_CODE (*node) != FUNCTION_DECL)
- {
- warning (OPT_Wattributes, "%qs attribute only applies to functions",
- IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle an "interrupt" or "isr" attribute;
- arguments as in struct attribute_spec.handler. */
-static tree
-arm_handle_isr_attribute (tree *node, tree name, tree args, int flags,
- bool *no_add_attrs)
-{
- if (DECL_P (*node))
- {
- if (TREE_CODE (*node) != FUNCTION_DECL)
- {
- warning (OPT_Wattributes, "%qs attribute only applies to functions",
- IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
- /* FIXME: the argument if any is checked for type attributes;
- should it be checked for decl ones? */
- }
- else
- {
- if (TREE_CODE (*node) == FUNCTION_TYPE
- || TREE_CODE (*node) == METHOD_TYPE)
- {
- if (arm_isr_value (args) == ARM_FT_UNKNOWN)
- {
- warning (OPT_Wattributes, "%qs attribute ignored",
- IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
- }
- else if (TREE_CODE (*node) == POINTER_TYPE
- && (TREE_CODE (TREE_TYPE (*node)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (*node)) == METHOD_TYPE)
- && arm_isr_value (args) != ARM_FT_UNKNOWN)
- {
- *node = build_variant_type_copy (*node);
- TREE_TYPE (*node) = build_type_attribute_variant
- (TREE_TYPE (*node),
- tree_cons (name, args, TYPE_ATTRIBUTES (TREE_TYPE (*node))));
- *no_add_attrs = true;
- }
- else
- {
- /* Possibly pass this attribute on from the type to a decl. */
- if (flags & ((int) ATTR_FLAG_DECL_NEXT
- | (int) ATTR_FLAG_FUNCTION_NEXT
- | (int) ATTR_FLAG_ARRAY_NEXT))
- {
- *no_add_attrs = true;
- return tree_cons (name, args, NULL_TREE);
- }
- else
- {
- warning (OPT_Wattributes, "%qs attribute ignored",
- IDENTIFIER_POINTER (name));
- }
- }
- }
-
- return NULL_TREE;
-}
-
-#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
-/* Handle the "notshared" attribute. This attribute is another way of
- requesting hidden visibility. ARM's compiler supports
- "__declspec(notshared)"; we support the same thing via an
- attribute. */
-
-static tree
-arm_handle_notshared_attribute (tree *node,
- tree name ATTRIBUTE_UNUSED,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED,
- bool *no_add_attrs)
-{
- tree decl = TYPE_NAME (*node);
-
- if (decl)
- {
- DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
- DECL_VISIBILITY_SPECIFIED (decl) = 1;
- *no_add_attrs = false;
- }
- return NULL_TREE;
-}
-#endif
-
-/* Return 0 if the attributes for two types are incompatible, 1 if they
- are compatible, and 2 if they are nearly compatible (which causes a
- warning to be generated). */
-static int
-arm_comp_type_attributes (tree type1, tree type2)
-{
- int l1, l2, s1, s2;
-
- /* Check for mismatch of non-default calling convention. */
- if (TREE_CODE (type1) != FUNCTION_TYPE)
- return 1;
-
- /* Check for mismatched call attributes. */
- l1 = lookup_attribute ("long_call", TYPE_ATTRIBUTES (type1)) != NULL;
- l2 = lookup_attribute ("long_call", TYPE_ATTRIBUTES (type2)) != NULL;
- s1 = lookup_attribute ("short_call", TYPE_ATTRIBUTES (type1)) != NULL;
- s2 = lookup_attribute ("short_call", TYPE_ATTRIBUTES (type2)) != NULL;
-
- /* Only bother to check if an attribute is defined. */
- if (l1 | l2 | s1 | s2)
- {
- /* If one type has an attribute, the other must have the same attribute. */
- if ((l1 != l2) || (s1 != s2))
- return 0;
-
- /* Disallow mixed attributes. */
- if ((l1 & s2) || (l2 & s1))
- return 0;
- }
-
- /* Check for mismatched ISR attribute. */
- l1 = lookup_attribute ("isr", TYPE_ATTRIBUTES (type1)) != NULL;
- if (! l1)
- l1 = lookup_attribute ("interrupt", TYPE_ATTRIBUTES (type1)) != NULL;
- l2 = lookup_attribute ("isr", TYPE_ATTRIBUTES (type2)) != NULL;
- if (! l2)
- l1 = lookup_attribute ("interrupt", TYPE_ATTRIBUTES (type2)) != NULL;
- if (l1 != l2)
- return 0;
-
- return 1;
-}
-
-/* Encode long_call or short_call attribute by prefixing
- symbol name in DECL with a special character FLAG. */
-void
-arm_encode_call_attribute (tree decl, int flag)
-{
- const char * str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
- int len = strlen (str);
- char * newstr;
-
- /* Do not allow weak functions to be treated as short call. */
- if (DECL_WEAK (decl) && flag == SHORT_CALL_FLAG_CHAR)
- return;
-
- newstr = alloca (len + 2);
- newstr[0] = flag;
- strcpy (newstr + 1, str);
-
- newstr = (char *) ggc_alloc_string (newstr, len + 1);
- XSTR (XEXP (DECL_RTL (decl), 0), 0) = newstr;
-}
-
-/* Assigns default attributes to newly defined type. This is used to
- set short_call/long_call attributes for function types of
- functions defined inside corresponding #pragma scopes. */
-static void
-arm_set_default_type_attributes (tree type)
-{
- /* Add __attribute__ ((long_call)) to all functions, when
- inside #pragma long_calls or __attribute__ ((short_call)),
- when inside #pragma no_long_calls. */
- if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
- {
- tree type_attr_list, attr_name;
- type_attr_list = TYPE_ATTRIBUTES (type);
-
- if (arm_pragma_long_calls == LONG)
- attr_name = get_identifier ("long_call");
- else if (arm_pragma_long_calls == SHORT)
- attr_name = get_identifier ("short_call");
- else
- return;
-
- type_attr_list = tree_cons (attr_name, NULL_TREE, type_attr_list);
- TYPE_ATTRIBUTES (type) = type_attr_list;
- }
-}
-
-/* Return 1 if the operand is a SYMBOL_REF for a function known to be
- defined within the current compilation unit. If this cannot be
- determined, then 0 is returned. */
-static int
-current_file_function_operand (rtx sym_ref)
-{
- /* This is a bit of a fib. A function will have a short call flag
- applied to its name if it has the short call attribute, or it has
- already been defined within the current compilation unit. */
- if (ENCODED_SHORT_CALL_ATTR_P (XSTR (sym_ref, 0)))
- return 1;
-
- /* The current function is always defined within the current compilation
- unit. If it s a weak definition however, then this may not be the real
- definition of the function, and so we have to say no. */
- if (sym_ref == XEXP (DECL_RTL (current_function_decl), 0)
- && !DECL_WEAK (current_function_decl))
- return 1;
-
- /* We cannot make the determination - default to returning 0. */
- return 0;
-}
-
-/* Return nonzero if a 32 bit "long_call" should be generated for
- this call. We generate a long_call if the function:
-
- a. has an __attribute__((long call))
- or b. is within the scope of a #pragma long_calls
- or c. the -mlong-calls command line switch has been specified
- . and either:
- 1. -ffunction-sections is in effect
- or 2. the current function has __attribute__ ((section))
- or 3. the target function has __attribute__ ((section))
-
- However we do not generate a long call if the function:
-
- d. has an __attribute__ ((short_call))
- or e. is inside the scope of a #pragma no_long_calls
- or f. is defined within the current compilation unit.
-
- This function will be called by C fragments contained in the machine
- description file. SYM_REF and CALL_COOKIE correspond to the matched
- rtl operands. CALL_SYMBOL is used to distinguish between
- two different callers of the function. It is set to 1 in the
- "call_symbol" and "call_symbol_value" patterns and to 0 in the "call"
- and "call_value" patterns. This is because of the difference in the
- SYM_REFs passed by these patterns. */
-int
-arm_is_longcall_p (rtx sym_ref, int call_cookie, int call_symbol)
-{
- if (!call_symbol)
- {
- if (GET_CODE (sym_ref) != MEM)
- return 0;
-
- sym_ref = XEXP (sym_ref, 0);
- }
-
- if (GET_CODE (sym_ref) != SYMBOL_REF)
- return 0;
-
- if (call_cookie & CALL_SHORT)
- return 0;
-
- if (TARGET_LONG_CALLS)
- {
- if (flag_function_sections
- || DECL_SECTION_NAME (current_function_decl))
- /* c.3 is handled by the definition of the
- ARM_DECLARE_FUNCTION_SIZE macro. */
- return 1;
- }
-
- if (current_file_function_operand (sym_ref))
- return 0;
-
- return (call_cookie & CALL_LONG)
- || ENCODED_LONG_CALL_ATTR_P (XSTR (sym_ref, 0))
- || TARGET_LONG_CALLS;
-}
-
-/* Return nonzero if it is ok to make a tail-call to DECL. */
-static bool
-arm_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
-{
- int call_type = TARGET_LONG_CALLS ? CALL_LONG : CALL_NORMAL;
-
- if (cfun->machine->sibcall_blocked)
- return false;
-
- /* Never tailcall something for which we have no decl, or if we
- are in Thumb mode. */
- if (decl == NULL || TARGET_THUMB)
- return false;
-
- /* Get the calling method. */
- if (lookup_attribute ("short_call", TYPE_ATTRIBUTES (TREE_TYPE (decl))))
- call_type = CALL_SHORT;
- else if (lookup_attribute ("long_call", TYPE_ATTRIBUTES (TREE_TYPE (decl))))
- call_type = CALL_LONG;
-
- /* Cannot tail-call to long calls, since these are out of range of
- a branch instruction. However, if not compiling PIC, we know
- we can reach the symbol if it is in this compilation unit. */
- if (call_type == CALL_LONG && (flag_pic || !TREE_ASM_WRITTEN (decl)))
- return false;
-
- /* If we are interworking and the function is not declared static
- then we can't tail-call it unless we know that it exists in this
- compilation unit (since it might be a Thumb routine). */
- if (TARGET_INTERWORK && TREE_PUBLIC (decl) && !TREE_ASM_WRITTEN (decl))
- return false;
-
- /* Never tailcall from an ISR routine - it needs a special exit sequence. */
- if (IS_INTERRUPT (arm_current_func_type ()))
- return false;
-
- /* Everything else is ok. */
- return true;
-}
-
-
-/* Addressing mode support functions. */
-
-/* Return nonzero if X is a legitimate immediate operand when compiling
- for PIC. We know that X satisfies CONSTANT_P and flag_pic is true. */
-int
-legitimate_pic_operand_p (rtx x)
-{
- if (GET_CODE (x) == SYMBOL_REF
- || (GET_CODE (x) == CONST
- && GET_CODE (XEXP (x, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF))
- return 0;
-
- return 1;
-}
-
-rtx
-legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
-{
- if (GET_CODE (orig) == SYMBOL_REF
- || GET_CODE (orig) == LABEL_REF)
- {
-#ifndef AOF_ASSEMBLER
- rtx pic_ref, address;
-#endif
- rtx insn;
- int subregs = 0;
-
- /* If this function doesn't have a pic register, create one now.
- A lot of the logic here is made obscure by the fact that this
- routine gets called as part of the rtx cost estimation
- process. We don't want those calls to affect any assumptions
- about the real function; and further, we can't call
- entry_of_function() until we start the real expansion
- process. */
- if (!current_function_uses_pic_offset_table)
- {
- gcc_assert (!no_new_pseudos);
- if (arm_pic_register != INVALID_REGNUM)
- {
- cfun->machine->pic_reg = gen_rtx_REG (Pmode, arm_pic_register);
-
- /* Play games to avoid marking the function as needing pic
- if we are being called as part of the cost-estimation
- process. */
- if (!ir_type() || currently_expanding_to_rtl)
- current_function_uses_pic_offset_table = 1;
- }
- else
- {
- rtx seq, entry;
-
- cfun->machine->pic_reg = gen_reg_rtx (Pmode);
-
- /* Play games to avoid marking the function as needing pic
- if we are being called as part of the cost-estimation
- process. */
- if (!ir_type() || currently_expanding_to_rtl)
- {
- current_function_uses_pic_offset_table = 1;
- start_sequence ();
-
- arm_load_pic_register (0UL);
-
- seq = get_insns ();
- end_sequence ();
-
- entry = entry_of_function_safe ();
- if (!entry)
- {
- gcc_assert (currently_expanding_to_rtl);
- entry = get_insns();
- }
-
- emit_insn_after (seq, entry);
- }
- }
- }
-
- if (reg == 0)
- {
- gcc_assert (!no_new_pseudos);
- reg = gen_reg_rtx (Pmode);
-
- subregs = 1;
- }
-
-#ifdef AOF_ASSEMBLER
- /* The AOF assembler can generate relocations for these directly, and
- understands that the PIC register has to be added into the offset. */
- insn = emit_insn (gen_pic_load_addr_based (reg, orig));
-#else
- if (subregs)
- address = gen_reg_rtx (Pmode);
- else
- address = reg;
-
- if (TARGET_ARM)
- emit_insn (gen_pic_load_addr_arm (address, orig));
- else
- emit_insn (gen_pic_load_addr_thumb (address, orig));
-
- if ((GET_CODE (orig) == LABEL_REF
- || (GET_CODE (orig) == SYMBOL_REF &&
- SYMBOL_REF_LOCAL_P (orig)))
- && NEED_GOT_RELOC)
- pic_ref = gen_rtx_PLUS (Pmode, cfun->machine->pic_reg, address);
- else
- {
- pic_ref = gen_const_mem (Pmode,
- gen_rtx_PLUS (Pmode, cfun->machine->pic_reg,
- address));
- }
-
- insn = emit_move_insn (reg, pic_ref);
-#endif
- /* Put a REG_EQUAL note on this insn, so that it can be optimized
- by loop. */
- REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig,
- REG_NOTES (insn));
- return reg;
- }
- else if (GET_CODE (orig) == CONST)
- {
- rtx base, offset;
-
- if (GET_CODE (XEXP (orig, 0)) == PLUS
- && XEXP (XEXP (orig, 0), 0) == cfun->machine->pic_reg)
- return orig;
-
- if (GET_CODE (XEXP (orig, 0)) == UNSPEC
- && XINT (XEXP (orig, 0), 1) == UNSPEC_TLS)
- return orig;
-
- if (reg == 0)
- {
- gcc_assert (!no_new_pseudos);
- reg = gen_reg_rtx (Pmode);
- }
-
- gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
-
- base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
- offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
- base == reg ? 0 : reg);
-
- if (GET_CODE (offset) == CONST_INT)
- {
- /* The base register doesn't really matter, we only want to
- test the index for the appropriate mode. */
- if (!arm_legitimate_index_p (mode, offset, SET, 0))
- {
- gcc_assert (!no_new_pseudos);
- offset = force_reg (Pmode, offset);
- }
-
- if (GET_CODE (offset) == CONST_INT)
- return plus_constant (base, INTVAL (offset));
- }
-
- if (GET_MODE_SIZE (mode) > 4
- && (GET_MODE_CLASS (mode) == MODE_INT
- || TARGET_SOFT_FLOAT))
- {
- emit_insn (gen_addsi3 (reg, base, offset));
- return reg;
- }
-
- return gen_rtx_PLUS (Pmode, base, offset);
- }
-
- return orig;
-}
-
-
-/* Find a spare low register to use during the prolog of a function. */
-
-static int
-thumb_find_work_register (unsigned long pushed_regs_mask)
-{
- int reg;
-
- /* Check the argument registers first as these are call-used. The
- register allocation order means that sometimes r3 might be used
- but earlier argument registers might not, so check them all. */
- for (reg = LAST_ARG_REGNUM; reg >= 0; reg --)
- if (!regs_ever_live[reg])
- return reg;
-
- /* Before going on to check the call-saved registers we can try a couple
- more ways of deducing that r3 is available. The first is when we are
- pushing anonymous arguments onto the stack and we have less than 4
- registers worth of fixed arguments(*). In this case r3 will be part of
- the variable argument list and so we can be sure that it will be
- pushed right at the start of the function. Hence it will be available
- for the rest of the prologue.
- (*): ie current_function_pretend_args_size is greater than 0. */
- if (cfun->machine->uses_anonymous_args
- && current_function_pretend_args_size > 0)
- return LAST_ARG_REGNUM;
-
- /* The other case is when we have fixed arguments but less than 4 registers
- worth. In this case r3 might be used in the body of the function, but
- it is not being used to convey an argument into the function. In theory
- we could just check current_function_args_size to see how many bytes are
- being passed in argument registers, but it seems that it is unreliable.
- Sometimes it will have the value 0 when in fact arguments are being
- passed. (See testcase execute/20021111-1.c for an example). So we also
- check the args_info.nregs field as well. The problem with this field is
- that it makes no allowances for arguments that are passed to the
- function but which are not used. Hence we could miss an opportunity
- when a function has an unused argument in r3. But it is better to be
- safe than to be sorry. */
- if (! cfun->machine->uses_anonymous_args
- && current_function_args_size >= 0
- && current_function_args_size <= (LAST_ARG_REGNUM * UNITS_PER_WORD)
- && cfun->args_info.nregs < 4)
- return LAST_ARG_REGNUM;
-
- /* Otherwise look for a call-saved register that is going to be pushed. */
- for (reg = LAST_LO_REGNUM; reg > LAST_ARG_REGNUM; reg --)
- if (pushed_regs_mask & (1 << reg))
- return reg;
-
- /* Something went wrong - thumb_compute_save_reg_mask()
- should have arranged for a suitable register to be pushed. */
- gcc_unreachable ();
-}
-
-static GTY(()) int pic_labelno;
-
-/* Generate code to load the PIC register. In thumb mode SCRATCH is a
- low register. */
-
-void
-arm_load_pic_register (unsigned long saved_regs ATTRIBUTE_UNUSED)
-{
-#ifndef AOF_ASSEMBLER
- rtx l1, labelno, pic_tmp, pic_tmp2, pic_rtx;
- rtx global_offset_table;
-
- if (current_function_uses_pic_offset_table == 0 || TARGET_SINGLE_PIC_BASE)
- return;
-
- gcc_assert (flag_pic);
-
- /* We use an UNSPEC rather than a LABEL_REF because this label never appears
- in the code stream. */
-
- labelno = GEN_INT (pic_labelno++);
- l1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, labelno), UNSPEC_PIC_LABEL);
- l1 = gen_rtx_CONST (VOIDmode, l1);
-
- global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
- /* On the ARM the PC register contains 'dot + 8' at the time of the
- addition, on the Thumb it is 'dot + 4'. */
- pic_tmp = plus_constant (l1, TARGET_ARM ? 8 : 4);
- if (GOT_PCREL)
- pic_tmp2 = gen_rtx_CONST (VOIDmode,
- gen_rtx_PLUS (Pmode, global_offset_table, pc_rtx));
- else
- pic_tmp2 = gen_rtx_CONST (VOIDmode, global_offset_table);
-
- pic_rtx = gen_rtx_CONST (Pmode, gen_rtx_MINUS (Pmode, pic_tmp2, pic_tmp));
-
- if (TARGET_ARM)
- {
- emit_insn (gen_pic_load_addr_arm (cfun->machine->pic_reg, pic_rtx));
- emit_insn (gen_pic_add_dot_plus_eight (cfun->machine->pic_reg,
- cfun->machine->pic_reg, labelno));
- }
- else
- {
- if (arm_pic_register != INVALID_REGNUM
- && REGNO (cfun->machine->pic_reg) > LAST_LO_REGNUM)
- {
- /* We will have pushed the pic register, so we should always be
- able to find a work register. */
- pic_tmp = gen_rtx_REG (SImode,
- thumb_find_work_register (saved_regs));
- emit_insn (gen_pic_load_addr_thumb (pic_tmp, pic_rtx));
- emit_insn (gen_movsi (pic_offset_table_rtx, pic_tmp));
- }
- else
- emit_insn (gen_pic_load_addr_thumb (cfun->machine->pic_reg, pic_rtx));
- emit_insn (gen_pic_add_dot_plus_four (cfun->machine->pic_reg,
- cfun->machine->pic_reg, labelno));
- }
-
- /* Need to emit this whether or not we obey regdecls,
- since setjmp/longjmp can cause life info to screw up. */
- emit_insn (gen_rtx_USE (VOIDmode, cfun->machine->pic_reg));
-#endif /* AOF_ASSEMBLER */
-}
-
-
-/* Return nonzero if X is valid as an ARM state addressing register. */
-static int
-arm_address_register_rtx_p (rtx x, int strict_p)
-{
- int regno;
-
- if (GET_CODE (x) != REG)
- return 0;
-
- regno = REGNO (x);
-
- if (strict_p)
- return ARM_REGNO_OK_FOR_BASE_P (regno);
-
- return (regno <= LAST_ARM_REGNUM
- || regno >= FIRST_PSEUDO_REGISTER
- || regno == FRAME_POINTER_REGNUM
- || regno == ARG_POINTER_REGNUM);
-}
-
-/* Return TRUE if this rtx is the difference of a symbol and a label,
- and will reduce to a PC-relative relocation in the object file.
- Expressions like this can be left alone when generating PIC, rather
- than forced through the GOT. */
-static int
-pcrel_constant_p (rtx x)
-{
- if (GET_CODE (x) == MINUS)
- return symbol_mentioned_p (XEXP (x, 0)) && label_mentioned_p (XEXP (x, 1));
-
- return FALSE;
-}
-
-/* Return nonzero if X is a valid ARM state address operand. */
-int
-arm_legitimate_address_p (enum machine_mode mode, rtx x, RTX_CODE outer,
- int strict_p)
-{
- bool use_ldrd;
- enum rtx_code code = GET_CODE (x);
-
- if (arm_address_register_rtx_p (x, strict_p))
- return 1;
-
- use_ldrd = (TARGET_LDRD
- && (mode == DImode
- || (mode == DFmode && (TARGET_SOFT_FLOAT || TARGET_VFP))));
-
- if (code == POST_INC || code == PRE_DEC
- || ((code == PRE_INC || code == POST_DEC)
- && (use_ldrd || GET_MODE_SIZE (mode) <= 4)))
- return arm_address_register_rtx_p (XEXP (x, 0), strict_p);
-
- else if ((code == POST_MODIFY || code == PRE_MODIFY)
- && arm_address_register_rtx_p (XEXP (x, 0), strict_p)
- && GET_CODE (XEXP (x, 1)) == PLUS
- && rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0)))
- {
- rtx addend = XEXP (XEXP (x, 1), 1);
-
- /* Don't allow ldrd post increment by register because it's hard
- to fixup invalid register choices. */
- if (use_ldrd
- && GET_CODE (x) == POST_MODIFY
- && GET_CODE (addend) == REG)
- return 0;
-
- return ((use_ldrd || GET_MODE_SIZE (mode) <= 4)
- && arm_legitimate_index_p (mode, addend, outer, strict_p));
- }
-
- /* After reload constants split into minipools will have addresses
- from a LABEL_REF. */
- else if (reload_completed
- && (code == LABEL_REF
- || (code == 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)))
- return 1;
-
- else if (mode == TImode)
- return 0;
-
- else if (code == PLUS)
- {
- rtx xop0 = XEXP (x, 0);
- rtx xop1 = XEXP (x, 1);
-
- return ((arm_address_register_rtx_p (xop0, strict_p)
- && arm_legitimate_index_p (mode, xop1, outer, strict_p))
- || (arm_address_register_rtx_p (xop1, strict_p)
- && arm_legitimate_index_p (mode, xop0, outer, strict_p)));
- }
-
-#if 0
- /* Reload currently can't handle MINUS, so disable this for now */
- else if (GET_CODE (x) == MINUS)
- {
- rtx xop0 = XEXP (x, 0);
- rtx xop1 = XEXP (x, 1);
-
- return (arm_address_register_rtx_p (xop0, strict_p)
- && arm_legitimate_index_p (mode, xop1, outer, strict_p));
- }
-#endif
-
- else if (GET_MODE_CLASS (mode) != MODE_FLOAT
- && code == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (x)
- && ! (flag_pic
- && symbol_mentioned_p (get_pool_constant (x))
- && ! pcrel_constant_p (get_pool_constant (x))))
- return 1;
-
- return 0;
-}
-
-/* Return nonzero if INDEX is valid for an address index operand in
- ARM state. */
-static int
-arm_legitimate_index_p (enum machine_mode mode, rtx index, RTX_CODE outer,
- int strict_p)
-{
- HOST_WIDE_INT range;
- enum rtx_code code = GET_CODE (index);
-
- /* Standard coprocessor addressing modes. */
- if (TARGET_HARD_FLOAT
- && (TARGET_FPA || TARGET_MAVERICK)
- && (GET_MODE_CLASS (mode) == MODE_FLOAT
- || (TARGET_MAVERICK && mode == DImode)))
- return (code == CONST_INT && INTVAL (index) < 1024
- && INTVAL (index) > -1024
- && (INTVAL (index) & 3) == 0);
-
- if (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (mode))
- {
- /* For DImode assume values will usually live in core regs
- and only allow LDRD addressing modes. */
- if (!TARGET_LDRD || mode != DImode)
- return (code == CONST_INT
- && INTVAL (index) < 1024
- && INTVAL (index) > -1024
- && (INTVAL (index) & 3) == 0);
- }
-
- if (arm_address_register_rtx_p (index, strict_p)
- && (GET_MODE_SIZE (mode) <= 4))
- return 1;
-
- if (mode == DImode || mode == DFmode)
- {
- if (code == CONST_INT)
- {
- HOST_WIDE_INT val = INTVAL (index);
-
- if (TARGET_LDRD)
- return val > -256 && val < 256;
- else
- return val > -4096 && val < 4092;
- }
-
- return TARGET_LDRD && arm_address_register_rtx_p (index, strict_p);
- }
-
- if (GET_MODE_SIZE (mode) <= 4
- && ! (arm_arch4
- && (mode == HImode
- || (mode == QImode && outer == SIGN_EXTEND))))
- {
- if (code == MULT)
- {
- rtx xiop0 = XEXP (index, 0);
- rtx xiop1 = XEXP (index, 1);
-
- return ((arm_address_register_rtx_p (xiop0, strict_p)
- && power_of_two_operand (xiop1, SImode))
- || (arm_address_register_rtx_p (xiop1, strict_p)
- && power_of_two_operand (xiop0, SImode)));
- }
- else if (code == LSHIFTRT || code == ASHIFTRT
- || code == ASHIFT || code == ROTATERT)
- {
- rtx op = XEXP (index, 1);
-
- return (arm_address_register_rtx_p (XEXP (index, 0), strict_p)
- && GET_CODE (op) == CONST_INT
- && INTVAL (op) > 0
- && INTVAL (op) <= 31);
- }
- }
-
- /* For ARM v4 we may be doing a sign-extend operation during the
- load. */
- if (arm_arch4)
- {
- if (mode == HImode || (outer == SIGN_EXTEND && mode == QImode))
- range = 256;
- else
- range = 4096;
- }
- else
- range = (mode == HImode) ? 4095 : 4096;
-
- return (code == CONST_INT
- && INTVAL (index) < range
- && INTVAL (index) > -range);
-}
-
-/* Return nonzero if X is valid as a Thumb state base register. */
-static int
-thumb_base_register_rtx_p (rtx x, enum machine_mode mode, int strict_p)
-{
- int regno;
-
- if (GET_CODE (x) != REG)
- return 0;
-
- regno = REGNO (x);
-
- if (strict_p)
- return THUMB_REGNO_MODE_OK_FOR_BASE_P (regno, mode);
-
- return (regno <= LAST_LO_REGNUM
- || regno > LAST_VIRTUAL_REGISTER
- || regno == FRAME_POINTER_REGNUM
- || (GET_MODE_SIZE (mode) >= 4
- && (regno == STACK_POINTER_REGNUM
- || regno >= FIRST_PSEUDO_REGISTER
- || x == hard_frame_pointer_rtx
- || x == arg_pointer_rtx)));
-}
-
-/* Return nonzero if x is a legitimate index register. This is the case
- for any base register that can access a QImode object. */
-inline static int
-thumb_index_register_rtx_p (rtx x, int strict_p)
-{
- return thumb_base_register_rtx_p (x, QImode, strict_p);
-}
-
-/* Return nonzero if x is a legitimate Thumb-state address.
-
- 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. */
-int
-thumb_legitimate_address_p (enum machine_mode mode, rtx x, int strict_p)
-{
- /* ??? 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)))
- return 0;
-
- /* Accept any base register. SP only in SImode or larger. */
- else if (thumb_base_register_rtx_p (x, mode, strict_p))
- return 1;
-
- /* This is PC relative data before arm_reorg runs. */
- else if (GET_MODE_SIZE (mode) >= 4 && CONSTANT_P (x)
- && GET_CODE (x) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (x) && !flag_pic)
- return 1;
-
- /* This is PC relative data after arm_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)))
- return 1;
-
- /* Post-inc indexing only supported for SImode and larger. */
- else if (GET_CODE (x) == POST_INC && GET_MODE_SIZE (mode) >= 4
- && thumb_index_register_rtx_p (XEXP (x, 0), strict_p))
- return 1;
-
- else if (GET_CODE (x) == PLUS)
- {
- /* REG+REG address can be any two index registers. */
- /* We 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
- && XEXP (x, 0) != frame_pointer_rtx
- && XEXP (x, 1) != frame_pointer_rtx
- && thumb_index_register_rtx_p (XEXP (x, 0), strict_p)
- && thumb_index_register_rtx_p (XEXP (x, 1), strict_p))
- return 1;
-
- /* REG+const has 5-7 bit offset for non-SP registers. */
- else if ((thumb_index_register_rtx_p (XEXP (x, 0), strict_p)
- || XEXP (x, 0) == arg_pointer_rtx)
- && GET_CODE (XEXP (x, 1)) == CONST_INT
- && thumb_legitimate_offset_p (mode, INTVAL (XEXP (x, 1))))
- return 1;
-
- /* 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
- && INTVAL (XEXP (x, 1)) >= 0
- && INTVAL (XEXP (x, 1)) + GET_MODE_SIZE (mode) <= 1024
- && (INTVAL (XEXP (x, 1)) & 3) == 0)
- return 1;
-
- else if (GET_CODE (XEXP (x, 0)) == REG
- && REGNO (XEXP (x, 0)) == FRAME_POINTER_REGNUM
- && GET_MODE_SIZE (mode) >= 4
- && GET_CODE (XEXP (x, 1)) == CONST_INT
- && (INTVAL (XEXP (x, 1)) & 3) == 0)
- return 1;
- }
-
- else if (GET_MODE_CLASS (mode) != MODE_FLOAT
- && GET_MODE_SIZE (mode) == 4
- && GET_CODE (x) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (x)
- && ! (flag_pic
- && symbol_mentioned_p (get_pool_constant (x))
- && ! pcrel_constant_p (get_pool_constant (x))))
- return 1;
-
- return 0;
-}
-
-/* Return nonzero if VAL can be used as an offset in a Thumb-state address
- instruction of mode MODE. */
-int
-thumb_legitimate_offset_p (enum machine_mode mode, HOST_WIDE_INT val)
-{
- switch (GET_MODE_SIZE (mode))
- {
- case 1:
- return val >= 0 && val < 32;
-
- case 2:
- return val >= 0 && val < 64 && (val & 1) == 0;
-
- default:
- return (val >= 0
- && (val + GET_MODE_SIZE (mode)) <= 128
- && (val & 3) == 0);
- }
-}
-
-/* Build the SYMBOL_REF for __tls_get_addr. */
-
-static GTY(()) rtx tls_get_addr_libfunc;
-
-static rtx
-get_tls_get_addr (void)
-{
- if (!tls_get_addr_libfunc)
- tls_get_addr_libfunc = init_one_libfunc ("__tls_get_addr");
- return tls_get_addr_libfunc;
-}
-
-static rtx
-arm_load_tp (rtx target)
-{
- if (!target)
- target = gen_reg_rtx (SImode);
-
- if (TARGET_HARD_TP)
- {
- /* Can return in any reg. */
- emit_insn (gen_load_tp_hard (target));
- }
- else
- {
- /* Always returned in r0. Immediately copy the result into a pseudo,
- otherwise other uses of r0 (e.g. setting up function arguments) may
- clobber the value. */
-
- rtx tmp;
-
- emit_insn (gen_load_tp_soft ());
-
- tmp = gen_rtx_REG (SImode, 0);
- emit_move_insn (target, tmp);
- }
- return target;
-}
-
-static rtx
-load_tls_operand (rtx x, rtx reg)
-{
- rtx tmp;
-
- if (reg == NULL_RTX)
- reg = gen_reg_rtx (SImode);
-
- tmp = gen_rtx_CONST (SImode, x);
-
- emit_move_insn (reg, tmp);
-
- return reg;
-}
-
-static rtx
-arm_call_tls_get_addr (rtx x, rtx reg, rtx *valuep, int reloc)
-{
- rtx insns, label, labelno, sum;
-
- start_sequence ();
-
- labelno = GEN_INT (pic_labelno++);
- label = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, labelno), UNSPEC_PIC_LABEL);
- label = gen_rtx_CONST (VOIDmode, label);
-
- sum = gen_rtx_UNSPEC (Pmode,
- gen_rtvec (4, x, GEN_INT (reloc), label,
- GEN_INT (TARGET_ARM ? 8 : 4)),
- UNSPEC_TLS);
- reg = load_tls_operand (sum, reg);
-
- if (TARGET_ARM)
- emit_insn (gen_pic_add_dot_plus_eight (reg, reg, labelno));
- else
- emit_insn (gen_pic_add_dot_plus_four (reg, reg, labelno));
-
- *valuep = emit_library_call_value (get_tls_get_addr (), NULL_RTX, LCT_PURE, /* LCT_CONST? */
- Pmode, 1, reg, Pmode);
-
- insns = get_insns ();
- end_sequence ();
-
- return insns;
-}
-
-rtx
-legitimize_tls_address (rtx x, rtx reg)
-{
- rtx dest, tp, label, labelno, sum, insns, ret, eqv, addend;
- unsigned int model = SYMBOL_REF_TLS_MODEL (x);
-
- switch (model)
- {
- case TLS_MODEL_GLOBAL_DYNAMIC:
- insns = arm_call_tls_get_addr (x, reg, &ret, TLS_GD32);
- dest = gen_reg_rtx (Pmode);
- emit_libcall_block (insns, dest, ret, x);
- return dest;
-
- case TLS_MODEL_LOCAL_DYNAMIC:
- insns = arm_call_tls_get_addr (x, reg, &ret, TLS_LDM32);
-
- /* Attach a unique REG_EQUIV, to allow the RTL optimizers to
- share the LDM result with other LD model accesses. */
- eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const1_rtx),
- UNSPEC_TLS);
- dest = gen_reg_rtx (Pmode);
- emit_libcall_block (insns, dest, ret, eqv);
-
- /* Load the addend. */
- addend = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, x, GEN_INT (TLS_LDO32)),
- UNSPEC_TLS);
- addend = force_reg (SImode, gen_rtx_CONST (SImode, addend));
- return gen_rtx_PLUS (Pmode, dest, addend);
-
- case TLS_MODEL_INITIAL_EXEC:
- labelno = GEN_INT (pic_labelno++);
- label = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, labelno), UNSPEC_PIC_LABEL);
- label = gen_rtx_CONST (VOIDmode, label);
- sum = gen_rtx_UNSPEC (Pmode,
- gen_rtvec (4, x, GEN_INT (TLS_IE32), label,
- GEN_INT (TARGET_ARM ? 8 : 4)),
- UNSPEC_TLS);
- reg = load_tls_operand (sum, reg);
-
- if (TARGET_ARM)
- emit_insn (gen_tls_load_dot_plus_eight (reg, reg, labelno));
- else
- {
- emit_insn (gen_pic_add_dot_plus_four (reg, reg, labelno));
- emit_move_insn (reg, gen_const_mem (SImode, reg));
- }
-
- tp = arm_load_tp (NULL_RTX);
-
- return gen_rtx_PLUS (Pmode, tp, reg);
-
- case TLS_MODEL_LOCAL_EXEC:
- tp = arm_load_tp (NULL_RTX);
-
- reg = gen_rtx_UNSPEC (Pmode,
- gen_rtvec (2, x, GEN_INT (TLS_LE32)),
- UNSPEC_TLS);
- reg = force_reg (SImode, gen_rtx_CONST (SImode, reg));
-
- return gen_rtx_PLUS (Pmode, tp, reg);
-
- default:
- abort ();
- }
-}
-
-/* Try machine-dependent ways of modifying an illegitimate address
- to be legitimate. If we find one, return the new, valid address. */
-rtx
-arm_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode)
-{
- if (arm_tls_symbol_p (x))
- return legitimize_tls_address (x, NULL_RTX);
-
- if (GET_CODE (x) == PLUS)
- {
- rtx xop0 = XEXP (x, 0);
- rtx xop1 = XEXP (x, 1);
-
- if (CONSTANT_P (xop0) && !symbol_mentioned_p (xop0))
- xop0 = force_reg (SImode, xop0);
-
- if (CONSTANT_P (xop1) && !symbol_mentioned_p (xop1))
- xop1 = force_reg (SImode, xop1);
-
- if (ARM_BASE_REGISTER_RTX_P (xop0)
- && GET_CODE (xop1) == CONST_INT)
- {
- HOST_WIDE_INT n, low_n;
- rtx base_reg, val;
- n = INTVAL (xop1);
-
- /* VFP addressing modes actually allow greater offsets, but for
- now we just stick with the lowest common denominator. */
- if (mode == DImode
- || ((TARGET_SOFT_FLOAT || TARGET_VFP) && mode == DFmode))
- {
- low_n = n & 0x0f;
- n &= ~0x0f;
- if (low_n > 4)
- {
- n += 16;
- low_n -= 16;
- }
- }
- else
- {
- low_n = ((mode) == TImode ? 0
- : n >= 0 ? (n & 0xfff) : -((-n) & 0xfff));
- n -= low_n;
- }
-
- base_reg = gen_reg_rtx (SImode);
- val = force_operand (plus_constant (xop0, n), NULL_RTX);
- emit_move_insn (base_reg, val);
- x = plus_constant (base_reg, low_n);
- }
- else if (xop0 != XEXP (x, 0) || xop1 != XEXP (x, 1))
- x = gen_rtx_PLUS (SImode, xop0, xop1);
- }
-
- /* XXX We don't allow MINUS any more -- see comment in
- arm_legitimate_address_p (). */
- else if (GET_CODE (x) == MINUS)
- {
- rtx xop0 = XEXP (x, 0);
- rtx xop1 = XEXP (x, 1);
-
- if (CONSTANT_P (xop0))
- xop0 = force_reg (SImode, xop0);
-
- if (CONSTANT_P (xop1) && ! symbol_mentioned_p (xop1))
- xop1 = force_reg (SImode, xop1);
-
- if (xop0 != XEXP (x, 0) || xop1 != XEXP (x, 1))
- x = gen_rtx_MINUS (SImode, xop0, xop1);
- }
-
- /* Make sure to take full advantage of the pre-indexed addressing mode
- with absolute addresses which often allows for the base register to
- be factorized for multiple adjacent memory references, and it might
- even allows for the mini pool to be avoided entirely. */
- else if (GET_CODE (x) == CONST_INT && optimize > 0)
- {
- unsigned int bits;
- HOST_WIDE_INT mask, base, index;
- rtx base_reg;
-
- /* ldr and ldrb can use a 12 bit index, ldrsb and the rest can only
- use a 8 bit index. So let's use a 12 bit index for SImode only and
- hope that arm_gen_constant will enable ldrb to use more bits. */
- bits = (mode == SImode) ? 12 : 8;
- mask = (1 << bits) - 1;
- base = INTVAL (x) & ~mask;
- index = INTVAL (x) & mask;
- if (bit_count (base & 0xffffffff) > (32 - bits)/2)
- {
- /* It'll most probably be more efficient to generate the base
- with more bits set and use a negative index instead. */
- base |= mask;
- index -= mask;
- }
- base_reg = force_reg (SImode, GEN_INT (base));
- x = plus_constant (base_reg, index);
- }
-
- if (flag_pic)
- {
- /* We need to find and carefully transform any SYMBOL and LABEL
- references; so go back to the original address expression. */
- rtx new_x = legitimize_pic_address (orig_x, mode, NULL_RTX);
-
- if (new_x != orig_x)
- x = new_x;
- }
-
- return x;
-}
-
-
-/* Try machine-dependent ways of modifying an illegitimate Thumb address
- to be legitimate. If we find one, return the new, valid address. */
-rtx
-thumb_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode)
-{
- if (arm_tls_symbol_p (x))
- return legitimize_tls_address (x, NULL_RTX);
-
- if (GET_CODE (x) == PLUS
- && GET_CODE (XEXP (x, 1)) == CONST_INT
- && (INTVAL (XEXP (x, 1)) >= 32 * GET_MODE_SIZE (mode)
- || INTVAL (XEXP (x, 1)) < 0))
- {
- rtx xop0 = XEXP (x, 0);
- rtx xop1 = XEXP (x, 1);
- HOST_WIDE_INT offset = INTVAL (xop1);
-
- /* Try and fold the offset into a biasing of the base register and
- then offsetting that. Don't do this when optimizing for space
- since it can cause too many CSEs. */
- if (optimize_size && offset >= 0
- && offset < 256 + 31 * GET_MODE_SIZE (mode))
- {
- HOST_WIDE_INT delta;
-
- if (offset >= 256)
- delta = offset - (256 - GET_MODE_SIZE (mode));
- else if (offset < 32 * GET_MODE_SIZE (mode) + 8)
- delta = 31 * GET_MODE_SIZE (mode);
- else
- delta = offset & (~31 * GET_MODE_SIZE (mode));
-
- xop0 = force_operand (plus_constant (xop0, offset - delta),
- NULL_RTX);
- x = plus_constant (xop0, delta);
- }
- else if (offset < 0 && offset > -256)
- /* Small negative offsets are best done with a subtract before the
- dereference, forcing these into a register normally takes two
- instructions. */
- x = force_operand (x, NULL_RTX);
- else
- {
- /* For the remaining cases, force the constant into a register. */
- xop1 = force_reg (SImode, xop1);
- x = gen_rtx_PLUS (SImode, xop0, xop1);
- }
- }
- else if (GET_CODE (x) == PLUS
- && s_register_operand (XEXP (x, 1), SImode)
- && !s_register_operand (XEXP (x, 0), SImode))
- {
- rtx xop0 = force_operand (XEXP (x, 0), NULL_RTX);
-
- x = gen_rtx_PLUS (SImode, xop0, XEXP (x, 1));
- }
-
- if (flag_pic)
- {
- /* We need to find and carefully transform any SYMBOL and LABEL
- references; so go back to the original address expression. */
- rtx new_x = legitimize_pic_address (orig_x, mode, NULL_RTX);
-
- if (new_x != orig_x)
- x = new_x;
- }
-
- return x;
-}
-
-rtx
-thumb_legitimize_reload_address (rtx *x_p,
- enum machine_mode mode,
- int opnum, int type,
- int ind_levels ATTRIBUTE_UNUSED)
-{
- rtx x = *x_p;
-
- if (GET_CODE (x) == PLUS
- && GET_MODE_SIZE (mode) < 4
- && REG_P (XEXP (x, 0))
- && XEXP (x, 0) == stack_pointer_rtx
- && GET_CODE (XEXP (x, 1)) == CONST_INT
- && !thumb_legitimate_offset_p (mode, INTVAL (XEXP (x, 1))))
- {
- rtx orig_x = x;
-
- x = copy_rtx (x);
- push_reload (orig_x, NULL_RTX, x_p, NULL, MODE_BASE_REG_CLASS (mode),
- Pmode, VOIDmode, 0, 0, opnum, type);
- return x;
- }
-
- /* If both registers are hi-regs, then it's better to reload the
- entire expression rather than each register individually. That
- only requires one reload register rather than two. */
- if (GET_CODE (x) == PLUS
- && REG_P (XEXP (x, 0))
- && REG_P (XEXP (x, 1))
- && !REG_MODE_OK_FOR_REG_BASE_P (XEXP (x, 0), mode)
- && !REG_MODE_OK_FOR_REG_BASE_P (XEXP (x, 1), mode))
- {
- rtx orig_x = x;
-
- x = copy_rtx (x);
- push_reload (orig_x, NULL_RTX, x_p, NULL, MODE_BASE_REG_CLASS (mode),
- Pmode, VOIDmode, 0, 0, opnum, type);
- return x;
- }
-
- return NULL;
-}
-
-/* Test for various thread-local symbols. */
-
-/* Return TRUE if X is a thread-local symbol. */
-
-static bool
-arm_tls_symbol_p (rtx x)
-{
- if (! TARGET_HAVE_TLS)
- return false;
-
- if (GET_CODE (x) != SYMBOL_REF)
- return false;
-
- return SYMBOL_REF_TLS_MODEL (x) != 0;
-}
-
-/* Helper for arm_tls_referenced_p. */
-
-static int
-arm_tls_operand_p_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (*x) == SYMBOL_REF)
- return SYMBOL_REF_TLS_MODEL (*x) != 0;
-
- /* Don't recurse into UNSPEC_TLS looking for TLS symbols; these are
- TLS offsets, not real symbol references. */
- if (GET_CODE (*x) == UNSPEC
- && XINT (*x, 1) == UNSPEC_TLS)
- return -1;
-
- return 0;
-}
-
-/* Return TRUE if X contains any TLS symbol references. */
-
-bool
-arm_tls_referenced_p (rtx x)
-{
- if (! TARGET_HAVE_TLS)
- return false;
-
- return for_each_rtx (&x, arm_tls_operand_p_1, NULL);
-}
-
-#define REG_OR_SUBREG_REG(X) \
- (GET_CODE (X) == REG \
- || (GET_CODE (X) == SUBREG && GET_CODE (SUBREG_REG (X)) == REG))
-
-#define REG_OR_SUBREG_RTX(X) \
- (GET_CODE (X) == REG ? (X) : SUBREG_REG (X))
-
-#ifndef COSTS_N_INSNS
-#define COSTS_N_INSNS(N) ((N) * 4 - 2)
-#endif
-static inline int
-thumb_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer)
-{
- enum machine_mode mode = GET_MODE (x);
-
- switch (code)
- {
- case ASHIFT:
- case ASHIFTRT:
- case LSHIFTRT:
- case ROTATERT:
- case PLUS:
- case MINUS:
- case COMPARE:
- case NEG:
- case NOT:
- return COSTS_N_INSNS (1);
-
- case MULT:
- if (GET_CODE (XEXP (x, 1)) == CONST_INT)
- {
- int cycles = 0;
- unsigned HOST_WIDE_INT i = INTVAL (XEXP (x, 1));
-
- while (i)
- {
- i >>= 2;
- cycles++;
- }
- return COSTS_N_INSNS (2) + cycles;
- }
- return COSTS_N_INSNS (1) + 16;
-
- case SET:
- return (COSTS_N_INSNS (1)
- + 4 * ((GET_CODE (SET_SRC (x)) == MEM)
- + GET_CODE (SET_DEST (x)) == MEM));
-
- case CONST_INT:
- if (outer == SET)
- {
- if ((unsigned HOST_WIDE_INT) 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 || outer == COMPARE)
- && INTVAL (x) < 256 && INTVAL (x) > -256)
- return 0;
- else if (outer == AND
- && INTVAL (x) < 256 && INTVAL (x) >= -256)
- return COSTS_N_INSNS (1);
- 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);
-
- case UDIV:
- case UMOD:
- case DIV:
- case MOD:
- return 100;
-
- case TRUNCATE:
- return 99;
-
- case AND:
- case XOR:
- case IOR:
- /* XXX guess. */
- return 8;
-
- case MEM:
- /* XXX another guess. */
- /* Memory costs quite a lot for the first word, but subsequent words
- load at the equivalent of a single insn each. */
- return (10 + 4 * ((GET_MODE_SIZE (mode) - 1) / UNITS_PER_WORD)
- + ((GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
- ? 4 : 0));
-
- case IF_THEN_ELSE:
- /* XXX a guess. */
- if (GET_CODE (XEXP (x, 1)) == PC || GET_CODE (XEXP (x, 2)) == PC)
- return 14;
- return 2;
-
- case ZERO_EXTEND:
- /* XXX still guessing. */
- switch (GET_MODE (XEXP (x, 0)))
- {
- case QImode:
- return (1 + (mode == DImode ? 4 : 0)
- + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
-
- case HImode:
- return (4 + (mode == DImode ? 4 : 0)
- + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
-
- case SImode:
- return (1 + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
-
- default:
- return 99;
- }
-
- default:
- return 99;
- }
-}
-
-
-/* Worker routine for arm_rtx_costs. */
-static inline int
-arm_rtx_costs_1 (rtx x, enum rtx_code code, enum rtx_code outer)
-{
- enum machine_mode mode = GET_MODE (x);
- enum rtx_code subcode;
- int extra_cost;
-
- switch (code)
- {
- case MEM:
- /* Memory costs quite a lot for the first word, but subsequent words
- load at the equivalent of a single insn each. */
- return (10 + 4 * ((GET_MODE_SIZE (mode) - 1) / UNITS_PER_WORD)
- + (GET_CODE (x) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (x) ? 4 : 0));
-
- case DIV:
- case MOD:
- case UDIV:
- case UMOD:
- return optimize_size ? COSTS_N_INSNS (2) : 100;
-
- case ROTATE:
- if (mode == SImode && GET_CODE (XEXP (x, 1)) == REG)
- return 4;
- /* Fall through */
- case ROTATERT:
- if (mode != SImode)
- return 8;
- /* Fall through */
- case ASHIFT: case LSHIFTRT: case ASHIFTRT:
- if (mode == DImode)
- return (8 + (GET_CODE (XEXP (x, 1)) == CONST_INT ? 0 : 8)
- + ((GET_CODE (XEXP (x, 0)) == REG
- || (GET_CODE (XEXP (x, 0)) == SUBREG
- && GET_CODE (SUBREG_REG (XEXP (x, 0))) == REG))
- ? 0 : 8));
- return (1 + ((GET_CODE (XEXP (x, 0)) == REG
- || (GET_CODE (XEXP (x, 0)) == SUBREG
- && GET_CODE (SUBREG_REG (XEXP (x, 0))) == REG))
- ? 0 : 4)
- + ((GET_CODE (XEXP (x, 1)) == REG
- || (GET_CODE (XEXP (x, 1)) == SUBREG
- && GET_CODE (SUBREG_REG (XEXP (x, 1))) == REG)
- || (GET_CODE (XEXP (x, 1)) == CONST_INT))
- ? 0 : 4));
-
- case MINUS:
- if (mode == DImode)
- return (4 + (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : 8)
- + ((REG_OR_SUBREG_REG (XEXP (x, 0))
- || (GET_CODE (XEXP (x, 0)) == CONST_INT
- && const_ok_for_arm (INTVAL (XEXP (x, 0)))))
- ? 0 : 8));
-
- if (GET_MODE_CLASS (mode) == MODE_FLOAT)
- return (2 + ((REG_OR_SUBREG_REG (XEXP (x, 1))
- || (GET_CODE (XEXP (x, 1)) == CONST_DOUBLE
- && arm_const_double_rtx (XEXP (x, 1))))
- ? 0 : 8)
- + ((REG_OR_SUBREG_REG (XEXP (x, 0))
- || (GET_CODE (XEXP (x, 0)) == CONST_DOUBLE
- && arm_const_double_rtx (XEXP (x, 0))))
- ? 0 : 8));
-
- if (((GET_CODE (XEXP (x, 0)) == CONST_INT
- && const_ok_for_arm (INTVAL (XEXP (x, 0)))
- && REG_OR_SUBREG_REG (XEXP (x, 1))))
- || (((subcode = GET_CODE (XEXP (x, 1))) == ASHIFT
- || subcode == ASHIFTRT || subcode == LSHIFTRT
- || subcode == ROTATE || subcode == ROTATERT
- || (subcode == MULT
- && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT
- && ((INTVAL (XEXP (XEXP (x, 1), 1)) &
- (INTVAL (XEXP (XEXP (x, 1), 1)) - 1)) == 0)))
- && REG_OR_SUBREG_REG (XEXP (XEXP (x, 1), 0))
- && (REG_OR_SUBREG_REG (XEXP (XEXP (x, 1), 1))
- || GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT)
- && REG_OR_SUBREG_REG (XEXP (x, 0))))
- return 1;
- /* Fall through */
-
- case PLUS:
- if (GET_CODE (XEXP (x, 0)) == MULT)
- {
- extra_cost = rtx_cost (XEXP (x, 0), code);
- if (!REG_OR_SUBREG_REG (XEXP (x, 1)))
- extra_cost += 4 * ARM_NUM_REGS (mode);
- return extra_cost;
- }
-
- if (GET_MODE_CLASS (mode) == MODE_FLOAT)
- return (2 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 8)
- + ((REG_OR_SUBREG_REG (XEXP (x, 1))
- || (GET_CODE (XEXP (x, 1)) == CONST_DOUBLE
- && arm_const_double_rtx (XEXP (x, 1))))
- ? 0 : 8));
-
- /* Fall through */
- case AND: case XOR: case IOR:
- extra_cost = 0;
-
- /* Normally the frame registers will be spilt into reg+const during
- reload, so it is a bad idea to combine them with other instructions,
- since then they might not be moved outside of loops. As a compromise
- we allow integration with ops that have a constant as their second
- operand. */
- if ((REG_OR_SUBREG_REG (XEXP (x, 0))
- && ARM_FRAME_RTX (REG_OR_SUBREG_RTX (XEXP (x, 0)))
- && GET_CODE (XEXP (x, 1)) != CONST_INT)
- || (REG_OR_SUBREG_REG (XEXP (x, 0))
- && ARM_FRAME_RTX (REG_OR_SUBREG_RTX (XEXP (x, 0)))))
- extra_cost = 4;
-
- if (mode == DImode)
- return (4 + extra_cost + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 8)
- + ((REG_OR_SUBREG_REG (XEXP (x, 1))
- || (GET_CODE (XEXP (x, 1)) == CONST_INT
- && const_ok_for_op (INTVAL (XEXP (x, 1)), code)))
- ? 0 : 8));
-
- if (REG_OR_SUBREG_REG (XEXP (x, 0)))
- return (1 + (GET_CODE (XEXP (x, 1)) == CONST_INT ? 0 : extra_cost)
- + ((REG_OR_SUBREG_REG (XEXP (x, 1))
- || (GET_CODE (XEXP (x, 1)) == CONST_INT
- && const_ok_for_op (INTVAL (XEXP (x, 1)), code)))
- ? 0 : 4));
-
- else if (REG_OR_SUBREG_REG (XEXP (x, 1)))
- return (1 + extra_cost
- + ((((subcode = GET_CODE (XEXP (x, 0))) == ASHIFT
- || subcode == LSHIFTRT || subcode == ASHIFTRT
- || subcode == ROTATE || subcode == ROTATERT
- || (subcode == MULT
- && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
- && ((INTVAL (XEXP (XEXP (x, 0), 1)) &
- (INTVAL (XEXP (XEXP (x, 0), 1)) - 1)) == 0)))
- && (REG_OR_SUBREG_REG (XEXP (XEXP (x, 0), 0)))
- && ((REG_OR_SUBREG_REG (XEXP (XEXP (x, 0), 1)))
- || GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))
- ? 0 : 4));
-
- return 8;
-
- case MULT:
- /* This should have been handled by the CPU specific routines. */
- gcc_unreachable ();
-
- case TRUNCATE:
- if (arm_arch3m && mode == SImode
- && GET_CODE (XEXP (x, 0)) == LSHIFTRT
- && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
- && (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0))
- == GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)))
- && (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == ZERO_EXTEND
- || GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == SIGN_EXTEND))
- return 8;
- return 99;
-
- case NEG:
- if (GET_MODE_CLASS (mode) == MODE_FLOAT)
- return 4 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 6);
- /* Fall through */
- case NOT:
- if (mode == DImode)
- return 4 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4);
-
- return 1 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4);
-
- case IF_THEN_ELSE:
- if (GET_CODE (XEXP (x, 1)) == PC || GET_CODE (XEXP (x, 2)) == PC)
- return 14;
- return 2;
-
- case COMPARE:
- return 1;
-
- case ABS:
- return 4 + (mode == DImode ? 4 : 0);
-
- case SIGN_EXTEND:
- if (GET_MODE (XEXP (x, 0)) == QImode)
- return (4 + (mode == DImode ? 4 : 0)
- + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
- /* Fall through */
- case ZERO_EXTEND:
- switch (GET_MODE (XEXP (x, 0)))
- {
- case QImode:
- return (1 + (mode == DImode ? 4 : 0)
- + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
-
- case HImode:
- return (4 + (mode == DImode ? 4 : 0)
- + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
-
- case SImode:
- return (1 + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
-
- case V8QImode:
- case V4HImode:
- case V2SImode:
- case V4QImode:
- case V2HImode:
- return 1;
-
- default:
- gcc_unreachable ();
- }
- gcc_unreachable ();
-
- case CONST_INT:
- if (const_ok_for_arm (INTVAL (x)))
- return outer == SET ? 2 : -1;
- else if (outer == AND
- && const_ok_for_arm (~INTVAL (x)))
- return -1;
- else if ((outer == COMPARE
- || outer == PLUS || outer == MINUS)
- && const_ok_for_arm (-INTVAL (x)))
- return -1;
- else
- return 5;
-
- case CONST:
- case LABEL_REF:
- case SYMBOL_REF:
- return 6;
-
- case CONST_DOUBLE:
- if (arm_const_double_rtx (x))
- return outer == SET ? 2 : -1;
- else if ((outer == COMPARE || outer == PLUS)
- && neg_const_double_rtx_ok_for_fpa (x))
- return -1;
- return 7;
-
- default:
- return 99;
- }
-}
-
-/* RTX costs when optimizing for size. */
-static bool
-arm_size_rtx_costs (rtx x, int code, int outer_code, int *total)
-{
- enum machine_mode mode = GET_MODE (x);
-
- if (TARGET_THUMB)
- {
- /* XXX TBD. For now, use the standard costs. */
- *total = thumb_rtx_costs (x, code, outer_code);
- return true;
- }
-
- switch (code)
- {
- case MEM:
- /* A memory access costs 1 insn if the mode is small, or the address is
- a single register, otherwise it costs one insn per word. */
- if (REG_P (XEXP (x, 0)))
- *total = COSTS_N_INSNS (1);
- else
- *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
- return true;
-
- case DIV:
- case MOD:
- case UDIV:
- case UMOD:
- /* Needs a libcall, so it costs about this. */
- *total = COSTS_N_INSNS (2);
- return false;
-
- case ROTATE:
- if (mode == SImode && GET_CODE (XEXP (x, 1)) == REG)
- {
- *total = COSTS_N_INSNS (2) + rtx_cost (XEXP (x, 0), code);
- return true;
- }
- /* Fall through */
- case ROTATERT:
- case ASHIFT:
- case LSHIFTRT:
- case ASHIFTRT:
- if (mode == DImode && GET_CODE (XEXP (x, 1)) == CONST_INT)
- {
- *total = COSTS_N_INSNS (3) + rtx_cost (XEXP (x, 0), code);
- return true;
- }
- else if (mode == SImode)
- {
- *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 0), code);
- /* Slightly disparage register shifts, but not by much. */
- if (GET_CODE (XEXP (x, 1)) != CONST_INT)
- *total += 1 + rtx_cost (XEXP (x, 1), code);
- return true;
- }
-
- /* Needs a libcall. */
- *total = COSTS_N_INSNS (2);
- return false;
-
- case MINUS:
- if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT)
- {
- *total = COSTS_N_INSNS (1);
- return false;
- }
-
- if (mode == SImode)
- {
- enum rtx_code subcode0 = GET_CODE (XEXP (x, 0));
- enum rtx_code subcode1 = GET_CODE (XEXP (x, 1));
-
- if (subcode0 == ROTATE || subcode0 == ROTATERT || subcode0 == ASHIFT
- || subcode0 == LSHIFTRT || subcode0 == ASHIFTRT
- || subcode1 == ROTATE || subcode1 == ROTATERT
- || subcode1 == ASHIFT || subcode1 == LSHIFTRT
- || subcode1 == ASHIFTRT)
- {
- /* It's just the cost of the two operands. */
- *total = 0;
- return false;
- }
-
- *total = COSTS_N_INSNS (1);
- return false;
- }
-
- *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
- return false;
-
- case PLUS:
- if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT)
- {
- *total = COSTS_N_INSNS (1);
- return false;
- }
-
- /* Fall through */
- case AND: case XOR: case IOR:
- if (mode == SImode)
- {
- enum rtx_code subcode = GET_CODE (XEXP (x, 0));
-
- if (subcode == ROTATE || subcode == ROTATERT || subcode == ASHIFT
- || subcode == LSHIFTRT || subcode == ASHIFTRT
- || (code == AND && subcode == NOT))
- {
- /* It's just the cost of the two operands. */
- *total = 0;
- return false;
- }
- }
-
- *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
- return false;
-
- case MULT:
- *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
- return false;
-
- case NEG:
- if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT)
- *total = COSTS_N_INSNS (1);
- /* Fall through */
- case NOT:
- *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
-
- return false;
-
- case IF_THEN_ELSE:
- *total = 0;
- return false;
-
- case COMPARE:
- if (cc_register (XEXP (x, 0), VOIDmode))
- * total = 0;
- else
- *total = COSTS_N_INSNS (1);
- return false;
-
- case ABS:
- if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT)
- *total = COSTS_N_INSNS (1);
- else
- *total = COSTS_N_INSNS (1 + ARM_NUM_REGS (mode));
- return false;
-
- case SIGN_EXTEND:
- *total = 0;
- if (GET_MODE_SIZE (GET_MODE (XEXP (x, 0))) < 4)
- {
- if (!(arm_arch4 && MEM_P (XEXP (x, 0))))
- *total += COSTS_N_INSNS (arm_arch6 ? 1 : 2);
- }
- if (mode == DImode)
- *total += COSTS_N_INSNS (1);
- return false;
-
- case ZERO_EXTEND:
- *total = 0;
- if (!(arm_arch4 && MEM_P (XEXP (x, 0))))
- {
- switch (GET_MODE (XEXP (x, 0)))
- {
- case QImode:
- *total += COSTS_N_INSNS (1);
- break;
-
- case HImode:
- *total += COSTS_N_INSNS (arm_arch6 ? 1 : 2);
-
- case SImode:
- break;
-
- default:
- *total += COSTS_N_INSNS (2);
- }
- }
-
- if (mode == DImode)
- *total += COSTS_N_INSNS (1);
-
- return false;
-
- case CONST_INT:
- if (const_ok_for_arm (INTVAL (x)))
- *total = COSTS_N_INSNS (outer_code == SET ? 1 : 0);
- else if (const_ok_for_arm (~INTVAL (x)))
- *total = COSTS_N_INSNS (outer_code == AND ? 0 : 1);
- else if (const_ok_for_arm (-INTVAL (x)))
- {
- if (outer_code == COMPARE || outer_code == PLUS
- || outer_code == MINUS)
- *total = 0;
- else
- *total = COSTS_N_INSNS (1);
- }
- else
- *total = COSTS_N_INSNS (2);
- return true;
-
- case CONST:
- case LABEL_REF:
- case SYMBOL_REF:
- *total = COSTS_N_INSNS (2);
- return true;
-
- case CONST_DOUBLE:
- *total = COSTS_N_INSNS (4);
- return true;
-
- default:
- if (mode != VOIDmode)
- *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
- else
- *total = COSTS_N_INSNS (4); /* How knows? */
- return false;
- }
-}
-
-/* RTX costs for cores with a slow MUL implementation. */
-
-static bool
-arm_slowmul_rtx_costs (rtx x, int code, int outer_code, int *total)
-{
- enum machine_mode mode = GET_MODE (x);
-
- if (TARGET_THUMB)
- {
- *total = thumb_rtx_costs (x, code, outer_code);
- return true;
- }
-
- switch (code)
- {
- case MULT:
- if (GET_MODE_CLASS (mode) == MODE_FLOAT
- || mode == DImode)
- {
- *total = 30;
- return true;
- }
-
- if (GET_CODE (XEXP (x, 1)) == CONST_INT)
- {
- unsigned HOST_WIDE_INT i = (INTVAL (XEXP (x, 1))
- & (unsigned HOST_WIDE_INT) 0xffffffff);
- int cost, const_ok = const_ok_for_arm (i);
- int j, booth_unit_size;
-
- /* Tune as appropriate. */
- cost = const_ok ? 4 : 8;
- booth_unit_size = 2;
- for (j = 0; i && j < 32; j += booth_unit_size)
- {
- i >>= booth_unit_size;
- cost += 2;
- }
-
- *total = cost;
- return true;
- }
-
- *total = 30 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4)
- + (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : 4);
- return true;
-
- default:
- *total = arm_rtx_costs_1 (x, code, outer_code);
- return true;
- }
-}
-
-
-/* RTX cost for cores with a fast multiply unit (M variants). */
-
-static bool
-arm_fastmul_rtx_costs (rtx x, int code, int outer_code, int *total)
-{
- enum machine_mode mode = GET_MODE (x);
-
- if (TARGET_THUMB)
- {
- *total = thumb_rtx_costs (x, code, outer_code);
- return true;
- }
-
- switch (code)
- {
- case MULT:
- /* There is no point basing this on the tuning, since it is always the
- fast variant if it exists at all. */
- if (mode == DImode
- && (GET_CODE (XEXP (x, 0)) == GET_CODE (XEXP (x, 1)))
- && (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
- || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND))
- {
- *total = 8;
- return true;
- }
-
-
- if (GET_MODE_CLASS (mode) == MODE_FLOAT
- || mode == DImode)
- {
- *total = 30;
- return true;
- }
-
- if (GET_CODE (XEXP (x, 1)) == CONST_INT)
- {
- unsigned HOST_WIDE_INT i = (INTVAL (XEXP (x, 1))
- & (unsigned HOST_WIDE_INT) 0xffffffff);
- int cost, const_ok = const_ok_for_arm (i);
- int j, booth_unit_size;
-
- /* Tune as appropriate. */
- cost = const_ok ? 4 : 8;
- booth_unit_size = 8;
- for (j = 0; i && j < 32; j += booth_unit_size)
- {
- i >>= booth_unit_size;
- cost += 2;
- }
-
- *total = cost;
- return true;
- }
-
- *total = 8 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4)
- + (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : 4);
- return true;
-
- default:
- *total = arm_rtx_costs_1 (x, code, outer_code);
- return true;
- }
-}
-
-
-/* RTX cost for XScale CPUs. */
-
-static bool
-arm_xscale_rtx_costs (rtx x, int code, int outer_code, int *total)
-{
- enum machine_mode mode = GET_MODE (x);
-
- if (TARGET_THUMB)
- {
- *total = thumb_rtx_costs (x, code, outer_code);
- return true;
- }
-
- switch (code)
- {
- case MULT:
- /* There is no point basing this on the tuning, since it is always the
- fast variant if it exists at all. */
- if (mode == DImode
- && (GET_CODE (XEXP (x, 0)) == GET_CODE (XEXP (x, 1)))
- && (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
- || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND))
- {
- *total = 8;
- return true;
- }
-
-
- if (GET_MODE_CLASS (mode) == MODE_FLOAT
- || mode == DImode)
- {
- *total = 30;
- return true;
- }
-
- if (GET_CODE (XEXP (x, 1)) == CONST_INT)
- {
- unsigned HOST_WIDE_INT i = (INTVAL (XEXP (x, 1))
- & (unsigned HOST_WIDE_INT) 0xffffffff);
- int cost, const_ok = const_ok_for_arm (i);
- unsigned HOST_WIDE_INT masked_const;
-
- /* The cost will be related to two insns.
- First a load of the constant (MOV or LDR), then a multiply. */
- cost = 2;
- if (! const_ok)
- cost += 1; /* LDR is probably more expensive because
- of longer result latency. */
- masked_const = i & 0xffff8000;
- if (masked_const != 0 && masked_const != 0xffff8000)
- {
- masked_const = i & 0xf8000000;
- if (masked_const == 0 || masked_const == 0xf8000000)
- cost += 1;
- else
- cost += 2;
- }
- *total = cost;
- return true;
- }
-
- *total = 8 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4)
- + (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : 4);
- return true;
-
- case COMPARE:
- /* A COMPARE of a MULT is slow on XScale; the muls instruction
- will stall until the multiplication is complete. */
- if (GET_CODE (XEXP (x, 0)) == MULT)
- *total = 4 + rtx_cost (XEXP (x, 0), code);
- else
- *total = arm_rtx_costs_1 (x, code, outer_code);
- return true;
-
- default:
- *total = arm_rtx_costs_1 (x, code, outer_code);
- return true;
- }
-}
-
-
-/* RTX costs for 9e (and later) cores. */
-
-static bool
-arm_9e_rtx_costs (rtx x, int code, int outer_code, int *total)
-{
- enum machine_mode mode = GET_MODE (x);
- int nonreg_cost;
- int cost;
-
- if (TARGET_THUMB)
- {
- switch (code)
- {
- case MULT:
- *total = COSTS_N_INSNS (3);
- return true;
-
- default:
- *total = thumb_rtx_costs (x, code, outer_code);
- return true;
- }
- }
-
- switch (code)
- {
- case MULT:
- /* There is no point basing this on the tuning, since it is always the
- fast variant if it exists at all. */
- if (mode == DImode
- && (GET_CODE (XEXP (x, 0)) == GET_CODE (XEXP (x, 1)))
- && (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
- || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND))
- {
- *total = 3;
- return true;
- }
-
-
- if (GET_MODE_CLASS (mode) == MODE_FLOAT)
- {
- *total = 30;
- return true;
- }
- if (mode == DImode)
- {
- cost = 7;
- nonreg_cost = 8;
- }
- else
- {
- cost = 2;
- nonreg_cost = 4;
- }
-
-
- *total = cost + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : nonreg_cost)
- + (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : nonreg_cost);
- return true;
-
- default:
- *total = arm_rtx_costs_1 (x, code, outer_code);
- return true;
- }
-}
-/* All address computations that can be done are free, but rtx cost returns
- the same for practically all of them. So we weight the different types
- of address here in the order (most pref first):
- PRE/POST_INC/DEC, SHIFT or NON-INT sum, INT sum, REG, MEM or LABEL. */
-static inline int
-arm_arm_address_cost (rtx x)
-{
- enum rtx_code c = GET_CODE (x);
-
- if (c == PRE_INC || c == PRE_DEC || c == POST_INC || c == POST_DEC)
- return 0;
- if (c == MEM || c == LABEL_REF || c == SYMBOL_REF)
- return 10;
-
- if (c == PLUS || c == MINUS)
- {
- if (GET_CODE (XEXP (x, 0)) == CONST_INT)
- return 2;
-
- if (ARITHMETIC_P (XEXP (x, 0)) || ARITHMETIC_P (XEXP (x, 1)))
- return 3;
-
- return 4;
- }
-
- return 6;
-}
-
-static inline int
-arm_thumb_address_cost (rtx x)
-{
- enum rtx_code c = GET_CODE (x);
-
- if (c == REG)
- return 1;
- if (c == PLUS
- && GET_CODE (XEXP (x, 0)) == REG
- && GET_CODE (XEXP (x, 1)) == CONST_INT)
- return 1;
-
- return 2;
-}
-
-static int
-arm_address_cost (rtx x)
-{
- return TARGET_ARM ? arm_arm_address_cost (x) : arm_thumb_address_cost (x);
-}
-
-static int
-arm_adjust_cost (rtx insn, rtx link, rtx dep, int cost)
-{
- rtx i_pat, d_pat;
-
- /* Some true dependencies can have a higher cost depending
- on precisely how certain input operands are used. */
- if (arm_tune_xscale
- && REG_NOTE_KIND (link) == 0
- && recog_memoized (insn) >= 0
- && recog_memoized (dep) >= 0)
- {
- int shift_opnum = get_attr_shift (insn);
- enum attr_type attr_type = get_attr_type (dep);
-
- /* If nonzero, SHIFT_OPNUM contains the operand number of a shifted
- operand for INSN. If we have a shifted input operand and the
- instruction we depend on is another ALU instruction, then we may
- have to account for an additional stall. */
- if (shift_opnum != 0
- && (attr_type == TYPE_ALU_SHIFT || attr_type == TYPE_ALU_SHIFT_REG))
- {
- rtx shifted_operand;
- int opno;
-
- /* Get the shifted operand. */
- extract_insn (insn);
- shifted_operand = recog_data.operand[shift_opnum];
-
- /* Iterate over all the operands in DEP. If we write an operand
- that overlaps with SHIFTED_OPERAND, then we have increase the
- cost of this dependency. */
- extract_insn (dep);
- preprocess_constraints ();
- for (opno = 0; opno < recog_data.n_operands; opno++)
- {
- /* We can ignore strict inputs. */
- if (recog_data.operand_type[opno] == OP_IN)
- continue;
-
- if (reg_overlap_mentioned_p (recog_data.operand[opno],
- shifted_operand))
- return 2;
- }
- }
- }
-
- /* XXX This is not strictly true for the FPA. */
- if (REG_NOTE_KIND (link) == REG_DEP_ANTI
- || REG_NOTE_KIND (link) == REG_DEP_OUTPUT)
- return 0;
-
- /* Call insns don't incur a stall, even if they follow a load. */
- if (REG_NOTE_KIND (link) == 0
- && GET_CODE (insn) == CALL_INSN)
- return 1;
-
- if ((i_pat = single_set (insn)) != NULL
- && GET_CODE (SET_SRC (i_pat)) == MEM
- && (d_pat = single_set (dep)) != NULL
- && GET_CODE (SET_DEST (d_pat)) == MEM)
- {
- rtx src_mem = XEXP (SET_SRC (i_pat), 0);
- /* This is a load after a store, there is no conflict if the load reads
- from a cached area. Assume that loads from the stack, and from the
- constant pool are cached, and that others will miss. This is a
- hack. */
-
- if ((GET_CODE (src_mem) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (src_mem))
- || reg_mentioned_p (stack_pointer_rtx, src_mem)
- || reg_mentioned_p (frame_pointer_rtx, src_mem)
- || reg_mentioned_p (hard_frame_pointer_rtx, src_mem))
- return 1;
- }
-
- return cost;
-}
-
-static int fp_consts_inited = 0;
-
-/* Only zero is valid for VFP. Other values are also valid for FPA. */
-static const char * const strings_fp[8] =
-{
- "0", "1", "2", "3",
- "4", "5", "0.5", "10"
-};
-
-static REAL_VALUE_TYPE values_fp[8];
-
-static void
-init_fp_table (void)
-{
- int i;
- REAL_VALUE_TYPE r;
-
- if (TARGET_VFP)
- fp_consts_inited = 1;
- else
- fp_consts_inited = 8;
-
- for (i = 0; i < fp_consts_inited; i++)
- {
- r = REAL_VALUE_ATOF (strings_fp[i], DFmode);
- values_fp[i] = r;
- }
-}
-
-/* Return TRUE if rtx X is a valid immediate FP constant. */
-int
-arm_const_double_rtx (rtx x)
-{
- REAL_VALUE_TYPE r;
- int i;
-
- if (!fp_consts_inited)
- init_fp_table ();
-
- REAL_VALUE_FROM_CONST_DOUBLE (r, x);
- if (REAL_VALUE_MINUS_ZERO (r))
- return 0;
-
- for (i = 0; i < fp_consts_inited; i++)
- if (REAL_VALUES_EQUAL (r, values_fp[i]))
- return 1;
-
- return 0;
-}
-
-/* Return TRUE if rtx X is a valid immediate FPA constant. */
-int
-neg_const_double_rtx_ok_for_fpa (rtx x)
-{
- REAL_VALUE_TYPE r;
- int i;
-
- if (!fp_consts_inited)
- init_fp_table ();
-
- REAL_VALUE_FROM_CONST_DOUBLE (r, x);
- r = REAL_VALUE_NEGATE (r);
- if (REAL_VALUE_MINUS_ZERO (r))
- return 0;
-
- for (i = 0; i < 8; i++)
- if (REAL_VALUES_EQUAL (r, values_fp[i]))
- return 1;
-
- return 0;
-}
-
-/* Predicates for `match_operand' and `match_operator'. */
-
-/* Return nonzero if OP is a valid Cirrus memory address pattern. */
-int
-cirrus_memory_offset (rtx op)
-{
- /* Reject eliminable registers. */
- if (! (reload_in_progress || reload_completed)
- && ( reg_mentioned_p (frame_pointer_rtx, op)
- || reg_mentioned_p (arg_pointer_rtx, op)
- || reg_mentioned_p (virtual_incoming_args_rtx, op)
- || reg_mentioned_p (virtual_outgoing_args_rtx, op)
- || reg_mentioned_p (virtual_stack_dynamic_rtx, op)
- || reg_mentioned_p (virtual_stack_vars_rtx, op)))
- return 0;
-
- if (GET_CODE (op) == MEM)
- {
- rtx ind;
-
- ind = XEXP (op, 0);
-
- /* Match: (mem (reg)). */
- if (GET_CODE (ind) == REG)
- return 1;
-
- /* Match:
- (mem (plus (reg)
- (const))). */
- if (GET_CODE (ind) == PLUS
- && GET_CODE (XEXP (ind, 0)) == REG
- && REG_MODE_OK_FOR_BASE_P (XEXP (ind, 0), VOIDmode)
- && GET_CODE (XEXP (ind, 1)) == CONST_INT)
- return 1;
- }
-
- return 0;
-}
-
-/* Return TRUE if OP is a valid coprocessor memory address pattern.
- WB if true if writeback address modes are allowed. */
-
-int
-arm_coproc_mem_operand (rtx op, bool wb)
-{
- rtx ind;
-
- /* Reject eliminable registers. */
- if (! (reload_in_progress || reload_completed)
- && ( reg_mentioned_p (frame_pointer_rtx, op)
- || reg_mentioned_p (arg_pointer_rtx, op)
- || reg_mentioned_p (virtual_incoming_args_rtx, op)
- || reg_mentioned_p (virtual_outgoing_args_rtx, op)
- || reg_mentioned_p (virtual_stack_dynamic_rtx, op)
- || reg_mentioned_p (virtual_stack_vars_rtx, op)))
- return FALSE;
-
- /* Constants are converted into offsets from labels. */
- if (GET_CODE (op) != MEM)
- return FALSE;
-
- ind = XEXP (op, 0);
-
- if (reload_completed
- && (GET_CODE (ind) == LABEL_REF
- || (GET_CODE (ind) == CONST
- && GET_CODE (XEXP (ind, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (ind, 0), 0)) == LABEL_REF
- && GET_CODE (XEXP (XEXP (ind, 0), 1)) == CONST_INT)))
- return TRUE;
-
- /* Match: (mem (reg)). */
- if (GET_CODE (ind) == REG)
- return arm_address_register_rtx_p (ind, 0);
-
- /* Autoincremment addressing modes. */
- if (wb
- && (GET_CODE (ind) == PRE_INC
- || GET_CODE (ind) == POST_INC
- || GET_CODE (ind) == PRE_DEC
- || GET_CODE (ind) == POST_DEC))
- return arm_address_register_rtx_p (XEXP (ind, 0), 0);
-
- if (wb
- && (GET_CODE (ind) == POST_MODIFY || GET_CODE (ind) == PRE_MODIFY)
- && arm_address_register_rtx_p (XEXP (ind, 0), 0)
- && GET_CODE (XEXP (ind, 1)) == PLUS
- && rtx_equal_p (XEXP (XEXP (ind, 1), 0), XEXP (ind, 0)))
- ind = XEXP (ind, 1);
-
- /* Match:
- (plus (reg)
- (const)). */
- if (GET_CODE (ind) == PLUS
- && GET_CODE (XEXP (ind, 0)) == REG
- && REG_MODE_OK_FOR_BASE_P (XEXP (ind, 0), VOIDmode)
- && GET_CODE (XEXP (ind, 1)) == CONST_INT
- && INTVAL (XEXP (ind, 1)) > -1024
- && INTVAL (XEXP (ind, 1)) < 1024
- && (INTVAL (XEXP (ind, 1)) & 3) == 0)
- return TRUE;
-
- return FALSE;
-}
-
-/* Return true if X is a register that will be eliminated later on. */
-int
-arm_eliminable_register (rtx x)
-{
- return REG_P (x) && (REGNO (x) == FRAME_POINTER_REGNUM
- || REGNO (x) == ARG_POINTER_REGNUM
- || (REGNO (x) >= FIRST_VIRTUAL_REGISTER
- && REGNO (x) <= LAST_VIRTUAL_REGISTER));
-}
-
-/* Return GENERAL_REGS if a scratch register required to reload x to/from
- coprocessor registers. Otherwise return NO_REGS. */
-
-enum reg_class
-coproc_secondary_reload_class (enum machine_mode mode, rtx x, bool wb)
-{
- if (arm_coproc_mem_operand (x, wb) || s_register_operand (x, mode))
- return NO_REGS;
-
- return GENERAL_REGS;
-}
-
-/* Values which must be returned in the most-significant end of the return
- register. */
-
-static bool
-arm_return_in_msb (tree valtype)
-{
- return (TARGET_AAPCS_BASED
- && BYTES_BIG_ENDIAN
- && (AGGREGATE_TYPE_P (valtype)
- || TREE_CODE (valtype) == COMPLEX_TYPE));
-}
-
-/* Returns TRUE if INSN is an "LDR REG, ADDR" instruction.
- Use by the Cirrus Maverick code which has to workaround
- a hardware bug triggered by such instructions. */
-static bool
-arm_memory_load_p (rtx insn)
-{
- rtx body, lhs, rhs;;
-
- if (insn == NULL_RTX || GET_CODE (insn) != INSN)
- return false;
-
- body = PATTERN (insn);
-
- if (GET_CODE (body) != SET)
- return false;
-
- lhs = XEXP (body, 0);
- rhs = XEXP (body, 1);
-
- lhs = REG_OR_SUBREG_RTX (lhs);
-
- /* If the destination is not a general purpose
- register we do not have to worry. */
- if (GET_CODE (lhs) != REG
- || REGNO_REG_CLASS (REGNO (lhs)) != GENERAL_REGS)
- return false;
-
- /* As well as loads from memory we also have to react
- to loads of invalid constants which will be turned
- into loads from the minipool. */
- return (GET_CODE (rhs) == MEM
- || GET_CODE (rhs) == SYMBOL_REF
- || note_invalid_constants (insn, -1, false));
-}
-
-/* Return TRUE if INSN is a Cirrus instruction. */
-static bool
-arm_cirrus_insn_p (rtx insn)
-{
- enum attr_cirrus attr;
-
- /* get_attr cannot accept USE or CLOBBER. */
- if (!insn
- || GET_CODE (insn) != INSN
- || GET_CODE (PATTERN (insn)) == USE
- || GET_CODE (PATTERN (insn)) == CLOBBER)
- return 0;
-
- attr = get_attr_cirrus (insn);
-
- return attr != CIRRUS_NOT;
-}
-
-/* Cirrus reorg for invalid instruction combinations. */
-static void
-cirrus_reorg (rtx first)
-{
- enum attr_cirrus attr;
- rtx body = PATTERN (first);
- rtx t;
- int nops;
-
- /* Any branch must be followed by 2 non Cirrus instructions. */
- if (GET_CODE (first) == JUMP_INSN && GET_CODE (body) != RETURN)
- {
- nops = 0;
- t = next_nonnote_insn (first);
-
- if (arm_cirrus_insn_p (t))
- ++ nops;
-
- if (arm_cirrus_insn_p (next_nonnote_insn (t)))
- ++ nops;
-
- while (nops --)
- emit_insn_after (gen_nop (), first);
-
- return;
- }
-
- /* (float (blah)) is in parallel with a clobber. */
- if (GET_CODE (body) == PARALLEL && XVECLEN (body, 0) > 0)
- body = XVECEXP (body, 0, 0);
-
- if (GET_CODE (body) == SET)
- {
- rtx lhs = XEXP (body, 0), rhs = XEXP (body, 1);
-
- /* cfldrd, cfldr64, cfstrd, cfstr64 must
- be followed by a non Cirrus insn. */
- if (get_attr_cirrus (first) == CIRRUS_DOUBLE)
- {
- if (arm_cirrus_insn_p (next_nonnote_insn (first)))
- emit_insn_after (gen_nop (), first);
-
- return;
- }
- else if (arm_memory_load_p (first))
- {
- unsigned int arm_regno;
-
- /* Any ldr/cfmvdlr, ldr/cfmvdhr, ldr/cfmvsr, ldr/cfmv64lr,
- ldr/cfmv64hr combination where the Rd field is the same
- in both instructions must be split with a non Cirrus
- insn. Example:
-
- ldr r0, blah
- nop
- cfmvsr mvf0, r0. */
-
- /* Get Arm register number for ldr insn. */
- if (GET_CODE (lhs) == REG)
- arm_regno = REGNO (lhs);
- else
- {
- gcc_assert (GET_CODE (rhs) == REG);
- arm_regno = REGNO (rhs);
- }
-
- /* Next insn. */
- first = next_nonnote_insn (first);
-
- if (! arm_cirrus_insn_p (first))
- return;
-
- body = PATTERN (first);
-
- /* (float (blah)) is in parallel with a clobber. */
- if (GET_CODE (body) == PARALLEL && XVECLEN (body, 0))
- body = XVECEXP (body, 0, 0);
-
- if (GET_CODE (body) == FLOAT)
- body = XEXP (body, 0);
-
- if (get_attr_cirrus (first) == CIRRUS_MOVE
- && GET_CODE (XEXP (body, 1)) == REG
- && arm_regno == REGNO (XEXP (body, 1)))
- emit_insn_after (gen_nop (), first);
-
- return;
- }
- }
-
- /* get_attr cannot accept USE or CLOBBER. */
- if (!first
- || GET_CODE (first) != INSN
- || GET_CODE (PATTERN (first)) == USE
- || GET_CODE (PATTERN (first)) == CLOBBER)
- return;
-
- attr = get_attr_cirrus (first);
-
- /* Any coprocessor compare instruction (cfcmps, cfcmpd, ...)
- must be followed by a non-coprocessor instruction. */
- if (attr == CIRRUS_COMPARE)
- {
- nops = 0;
-
- t = next_nonnote_insn (first);
-
- if (arm_cirrus_insn_p (t))
- ++ nops;
-
- if (arm_cirrus_insn_p (next_nonnote_insn (t)))
- ++ nops;
-
- while (nops --)
- emit_insn_after (gen_nop (), first);
-
- return;
- }
-}
-
-/* Return TRUE if X references a SYMBOL_REF. */
-int
-symbol_mentioned_p (rtx x)
-{
- const char * fmt;
- int i;
-
- if (GET_CODE (x) == SYMBOL_REF)
- return 1;
-
- /* UNSPEC_TLS entries for a symbol include the SYMBOL_REF, but they
- are constant offsets, not symbols. */
- if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLS)
- return 0;
-
- fmt = GET_RTX_FORMAT (GET_CODE (x));
-
- for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'E')
- {
- int j;
-
- for (j = XVECLEN (x, i) - 1; j >= 0; j--)
- if (symbol_mentioned_p (XVECEXP (x, i, j)))
- return 1;
- }
- else if (fmt[i] == 'e' && symbol_mentioned_p (XEXP (x, i)))
- return 1;
- }
-
- return 0;
-}
-
-/* Return TRUE if X references a LABEL_REF. */
-int
-label_mentioned_p (rtx x)
-{
- const char * fmt;
- int i;
-
- if (GET_CODE (x) == LABEL_REF)
- return 1;
-
- /* UNSPEC_TLS entries for a symbol include a LABEL_REF for the referencing
- instruction, but they are constant offsets, not symbols. */
- if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLS)
- return 0;
-
- fmt = GET_RTX_FORMAT (GET_CODE (x));
- for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'E')
- {
- int j;
-
- for (j = XVECLEN (x, i) - 1; j >= 0; j--)
- if (label_mentioned_p (XVECEXP (x, i, j)))
- return 1;
- }
- else if (fmt[i] == 'e' && label_mentioned_p (XEXP (x, i)))
- return 1;
- }
-
- return 0;
-}
-
-int
-tls_mentioned_p (rtx x)
-{
- switch (GET_CODE (x))
- {
- case CONST:
- return tls_mentioned_p (XEXP (x, 0));
-
- case UNSPEC:
- if (XINT (x, 1) == UNSPEC_TLS)
- return 1;
-
- default:
- return 0;
- }
-}
-
-/* Must not copy a SET whose source operand is PC-relative. */
-
-static bool
-arm_cannot_copy_insn_p (rtx insn)
-{
- rtx pat = PATTERN (insn);
-
- if (GET_CODE (pat) == PARALLEL
- && GET_CODE (XVECEXP (pat, 0, 0)) == SET)
- {
- rtx rhs = SET_SRC (XVECEXP (pat, 0, 0));
-
- if (GET_CODE (rhs) == UNSPEC
- && XINT (rhs, 1) == UNSPEC_PIC_BASE)
- return TRUE;
-
- if (GET_CODE (rhs) == MEM
- && GET_CODE (XEXP (rhs, 0)) == UNSPEC
- && XINT (XEXP (rhs, 0), 1) == UNSPEC_PIC_BASE)
- return TRUE;
- }
-
- return FALSE;
-}
-
-enum rtx_code
-minmax_code (rtx x)
-{
- enum rtx_code code = GET_CODE (x);
-
- switch (code)
- {
- case SMAX:
- return GE;
- case SMIN:
- return LE;
- case UMIN:
- return LEU;
- case UMAX:
- return GEU;
- default:
- gcc_unreachable ();
- }
-}
-
-/* Return 1 if memory locations are adjacent. */
-int
-adjacent_mem_locations (rtx a, rtx b)
-{
- /* We don't guarantee to preserve the order of these memory refs. */
- if (volatile_refs_p (a) || volatile_refs_p (b))
- return 0;
-
- if ((GET_CODE (XEXP (a, 0)) == REG
- || (GET_CODE (XEXP (a, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (a, 0), 1)) == CONST_INT))
- && (GET_CODE (XEXP (b, 0)) == REG
- || (GET_CODE (XEXP (b, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (b, 0), 1)) == CONST_INT)))
- {
- HOST_WIDE_INT val0 = 0, val1 = 0;
- rtx reg0, reg1;
- int val_diff;
-
- if (GET_CODE (XEXP (a, 0)) == PLUS)
- {
- reg0 = XEXP (XEXP (a, 0), 0);
- val0 = INTVAL (XEXP (XEXP (a, 0), 1));
- }
- else
- reg0 = XEXP (a, 0);
-
- if (GET_CODE (XEXP (b, 0)) == PLUS)
- {
- reg1 = XEXP (XEXP (b, 0), 0);
- val1 = INTVAL (XEXP (XEXP (b, 0), 1));
- }
- else
- reg1 = XEXP (b, 0);
-
- /* Don't accept any offset that will require multiple
- instructions to handle, since this would cause the
- arith_adjacentmem pattern to output an overlong sequence. */
- if (!const_ok_for_op (PLUS, val0) || !const_ok_for_op (PLUS, val1))
- return 0;
-
- /* Don't allow an eliminable register: register elimination can make
- the offset too large. */
- if (arm_eliminable_register (reg0))
- return 0;
-
- val_diff = val1 - val0;
-
- if (arm_ld_sched)
- {
- /* If the target has load delay slots, then there's no benefit
- to using an ldm instruction unless the offset is zero and
- we are optimizing for size. */
- return (optimize_size && (REGNO (reg0) == REGNO (reg1))
- && (val0 == 0 || val1 == 0 || val0 == 4 || val1 == 4)
- && (val_diff == 4 || val_diff == -4));
- }
-
- return ((REGNO (reg0) == REGNO (reg1))
- && (val_diff == 4 || val_diff == -4));
- }
-
- return 0;
-}
-
-int
-load_multiple_sequence (rtx *operands, int nops, int *regs, int *base,
- HOST_WIDE_INT *load_offset)
-{
- int unsorted_regs[4];
- HOST_WIDE_INT unsorted_offsets[4];
- int order[4];
- int base_reg = -1;
- int i;
-
- /* Can only handle 2, 3, or 4 insns at present,
- though could be easily extended if required. */
- gcc_assert (nops >= 2 && nops <= 4);
-
- /* Loop over the operands and check that the memory references are
- suitable (i.e. immediate offsets from the same base register). At
- the same time, extract the target register, and the memory
- offsets. */
- for (i = 0; i < nops; i++)
- {
- rtx reg;
- rtx offset;
-
- /* Convert a subreg of a mem into the mem itself. */
- if (GET_CODE (operands[nops + i]) == SUBREG)
- operands[nops + i] = alter_subreg (operands + (nops + i));
-
- gcc_assert (GET_CODE (operands[nops + i]) == MEM);
-
- /* Don't reorder volatile memory references; it doesn't seem worth
- looking for the case where the order is ok anyway. */
- if (MEM_VOLATILE_P (operands[nops + i]))
- return 0;
-
- offset = const0_rtx;
-
- if ((GET_CODE (reg = XEXP (operands[nops + i], 0)) == REG
- || (GET_CODE (reg) == SUBREG
- && GET_CODE (reg = SUBREG_REG (reg)) == REG))
- || (GET_CODE (XEXP (operands[nops + i], 0)) == PLUS
- && ((GET_CODE (reg = XEXP (XEXP (operands[nops + i], 0), 0))
- == REG)
- || (GET_CODE (reg) == SUBREG
- && GET_CODE (reg = SUBREG_REG (reg)) == REG))
- && (GET_CODE (offset = XEXP (XEXP (operands[nops + i], 0), 1))
- == CONST_INT)))
- {
- if (i == 0)
- {
- base_reg = REGNO (reg);
- unsorted_regs[0] = (GET_CODE (operands[i]) == REG
- ? REGNO (operands[i])
- : REGNO (SUBREG_REG (operands[i])));
- order[0] = 0;
- }
- else
- {
- if (base_reg != (int) REGNO (reg))
- /* Not addressed from the same base register. */
- return 0;
-
- unsorted_regs[i] = (GET_CODE (operands[i]) == REG
- ? REGNO (operands[i])
- : REGNO (SUBREG_REG (operands[i])));
- if (unsorted_regs[i] < unsorted_regs[order[0]])
- order[0] = i;
- }
-
- /* If it isn't an integer register, or if it overwrites the
- base register but isn't the last insn in the list, then
- we can't do this. */
- if (unsorted_regs[i] < 0 || unsorted_regs[i] > 14
- || (i != nops - 1 && unsorted_regs[i] == base_reg))
- return 0;
-
- unsorted_offsets[i] = INTVAL (offset);
- }
- else
- /* Not a suitable memory address. */
- return 0;
- }
-
- /* All the useful information has now been extracted from the
- operands into unsorted_regs and unsorted_offsets; additionally,
- order[0] has been set to the lowest numbered register in the
- list. Sort the registers into order, and check that the memory
- offsets are ascending and adjacent. */
-
- for (i = 1; i < nops; i++)
- {
- int j;
-
- order[i] = order[i - 1];
- for (j = 0; j < nops; j++)
- if (unsorted_regs[j] > unsorted_regs[order[i - 1]]
- && (order[i] == order[i - 1]
- || unsorted_regs[j] < unsorted_regs[order[i]]))
- order[i] = j;
-
- /* Have we found a suitable register? if not, one must be used more
- than once. */
- if (order[i] == order[i - 1])
- return 0;
-
- /* Is the memory address adjacent and ascending? */
- if (unsorted_offsets[order[i]] != unsorted_offsets[order[i - 1]] + 4)
- return 0;
- }
-
- if (base)
- {
- *base = base_reg;
-
- for (i = 0; i < nops; i++)
- regs[i] = unsorted_regs[order[i]];
-
- *load_offset = unsorted_offsets[order[0]];
- }
-
- if (unsorted_offsets[order[0]] == 0)
- return 1; /* ldmia */
-
- if (unsorted_offsets[order[0]] == 4)
- return 2; /* ldmib */
-
- if (unsorted_offsets[order[nops - 1]] == 0)
- return 3; /* ldmda */
-
- if (unsorted_offsets[order[nops - 1]] == -4)
- return 4; /* ldmdb */
-
- /* For ARM8,9 & StrongARM, 2 ldr instructions are faster than an ldm
- if the offset isn't small enough. The reason 2 ldrs are faster
- is because these ARMs are able to do more than one cache access
- in a single cycle. The ARM9 and StrongARM have Harvard caches,
- whilst the ARM8 has a double bandwidth cache. This means that
- these cores can do both an instruction fetch and a data fetch in
- a single cycle, so the trick of calculating the address into a
- scratch register (one of the result regs) and then doing a load
- multiple actually becomes slower (and no smaller in code size).
- That is the transformation
-
- ldr rd1, [rbase + offset]
- ldr rd2, [rbase + offset + 4]
-
- to
-
- add rd1, rbase, offset
- ldmia rd1, {rd1, rd2}
-
- produces worse code -- '3 cycles + any stalls on rd2' instead of
- '2 cycles + any stalls on rd2'. On ARMs with only one cache
- access per cycle, the first sequence could never complete in less
- than 6 cycles, whereas the ldm sequence would only take 5 and
- would make better use of sequential accesses if not hitting the
- cache.
-
- We cheat here and test 'arm_ld_sched' which we currently know to
- only be true for the ARM8, ARM9 and StrongARM. If this ever
- changes, then the test below needs to be reworked. */
- if (nops == 2 && arm_ld_sched)
- return 0;
-
- /* Can't do it without setting up the offset, only do this if it takes
- no more than one insn. */
- return (const_ok_for_arm (unsorted_offsets[order[0]])
- || const_ok_for_arm (-unsorted_offsets[order[0]])) ? 5 : 0;
-}
-
-const char *
-emit_ldm_seq (rtx *operands, int nops)
-{
- int regs[4];
- int base_reg;
- HOST_WIDE_INT offset;
- char buf[100];
- int i;
-
- switch (load_multiple_sequence (operands, nops, regs, &base_reg, &offset))
- {
- case 1:
- strcpy (buf, "ldm%?ia\t");
- break;
-
- case 2:
- strcpy (buf, "ldm%?ib\t");
- break;
-
- case 3:
- strcpy (buf, "ldm%?da\t");
- break;
-
- case 4:
- strcpy (buf, "ldm%?db\t");
- break;
-
- case 5:
- if (offset >= 0)
- sprintf (buf, "add%%?\t%s%s, %s%s, #%ld", REGISTER_PREFIX,
- reg_names[regs[0]], REGISTER_PREFIX, reg_names[base_reg],
- (long) offset);
- else
- sprintf (buf, "sub%%?\t%s%s, %s%s, #%ld", REGISTER_PREFIX,
- reg_names[regs[0]], REGISTER_PREFIX, reg_names[base_reg],
- (long) -offset);
- output_asm_insn (buf, operands);
- base_reg = regs[0];
- strcpy (buf, "ldm%?ia\t");
- break;
-
- default:
- gcc_unreachable ();
- }
-
- sprintf (buf + strlen (buf), "%s%s, {%s%s", REGISTER_PREFIX,
- reg_names[base_reg], REGISTER_PREFIX, reg_names[regs[0]]);
-
- for (i = 1; i < nops; i++)
- sprintf (buf + strlen (buf), ", %s%s", REGISTER_PREFIX,
- reg_names[regs[i]]);
-
- strcat (buf, "}\t%@ phole ldm");
-
- output_asm_insn (buf, operands);
- return "";
-}
-
-int
-store_multiple_sequence (rtx *operands, int nops, int *regs, int *base,
- HOST_WIDE_INT * load_offset)
-{
- int unsorted_regs[4];
- HOST_WIDE_INT unsorted_offsets[4];
- int order[4];
- int base_reg = -1;
- int i;
-
- /* Can only handle 2, 3, or 4 insns at present, though could be easily
- extended if required. */
- gcc_assert (nops >= 2 && nops <= 4);
-
- /* Loop over the operands and check that the memory references are
- suitable (i.e. immediate offsets from the same base register). At
- the same time, extract the target register, and the memory
- offsets. */
- for (i = 0; i < nops; i++)
- {
- rtx reg;
- rtx offset;
-
- /* Convert a subreg of a mem into the mem itself. */
- if (GET_CODE (operands[nops + i]) == SUBREG)
- operands[nops + i] = alter_subreg (operands + (nops + i));
-
- gcc_assert (GET_CODE (operands[nops + i]) == MEM);
-
- /* Don't reorder volatile memory references; it doesn't seem worth
- looking for the case where the order is ok anyway. */
- if (MEM_VOLATILE_P (operands[nops + i]))
- return 0;
-
- offset = const0_rtx;
-
- if ((GET_CODE (reg = XEXP (operands[nops + i], 0)) == REG
- || (GET_CODE (reg) == SUBREG
- && GET_CODE (reg = SUBREG_REG (reg)) == REG))
- || (GET_CODE (XEXP (operands[nops + i], 0)) == PLUS
- && ((GET_CODE (reg = XEXP (XEXP (operands[nops + i], 0), 0))
- == REG)
- || (GET_CODE (reg) == SUBREG
- && GET_CODE (reg = SUBREG_REG (reg)) == REG))
- && (GET_CODE (offset = XEXP (XEXP (operands[nops + i], 0), 1))
- == CONST_INT)))
- {
- if (i == 0)
- {
- base_reg = REGNO (reg);
- unsorted_regs[0] = (GET_CODE (operands[i]) == REG
- ? REGNO (operands[i])
- : REGNO (SUBREG_REG (operands[i])));
- order[0] = 0;
- }
- else
- {
- if (base_reg != (int) REGNO (reg))
- /* Not addressed from the same base register. */
- return 0;
-
- unsorted_regs[i] = (GET_CODE (operands[i]) == REG
- ? REGNO (operands[i])
- : REGNO (SUBREG_REG (operands[i])));
- if (unsorted_regs[i] < unsorted_regs[order[0]])
- order[0] = i;
- }
-
- /* If it isn't an integer register, then we can't do this. */
- if (unsorted_regs[i] < 0 || unsorted_regs[i] > 14)
- return 0;
-
- unsorted_offsets[i] = INTVAL (offset);
- }
- else
- /* Not a suitable memory address. */
- return 0;
- }
-
- /* All the useful information has now been extracted from the
- operands into unsorted_regs and unsorted_offsets; additionally,
- order[0] has been set to the lowest numbered register in the
- list. Sort the registers into order, and check that the memory
- offsets are ascending and adjacent. */
-
- for (i = 1; i < nops; i++)
- {
- int j;
-
- order[i] = order[i - 1];
- for (j = 0; j < nops; j++)
- if (unsorted_regs[j] > unsorted_regs[order[i - 1]]
- && (order[i] == order[i - 1]
- || unsorted_regs[j] < unsorted_regs[order[i]]))
- order[i] = j;
-
- /* Have we found a suitable register? if not, one must be used more
- than once. */
- if (order[i] == order[i - 1])
- return 0;
-
- /* Is the memory address adjacent and ascending? */
- if (unsorted_offsets[order[i]] != unsorted_offsets[order[i - 1]] + 4)
- return 0;
- }
-
- if (base)
- {
- *base = base_reg;
-
- for (i = 0; i < nops; i++)
- regs[i] = unsorted_regs[order[i]];
-
- *load_offset = unsorted_offsets[order[0]];
- }
-
- if (unsorted_offsets[order[0]] == 0)
- return 1; /* stmia */
-
- if (unsorted_offsets[order[0]] == 4)
- return 2; /* stmib */
-
- if (unsorted_offsets[order[nops - 1]] == 0)
- return 3; /* stmda */
-
- if (unsorted_offsets[order[nops - 1]] == -4)
- return 4; /* stmdb */
-
- return 0;
-}
-
-const char *
-emit_stm_seq (rtx *operands, int nops)
-{
- int regs[4];
- int base_reg;
- HOST_WIDE_INT offset;
- char buf[100];
- int i;
-
- switch (store_multiple_sequence (operands, nops, regs, &base_reg, &offset))
- {
- case 1:
- strcpy (buf, "stm%?ia\t");
- break;
-
- case 2:
- strcpy (buf, "stm%?ib\t");
- break;
-
- case 3:
- strcpy (buf, "stm%?da\t");
- break;
-
- case 4:
- strcpy (buf, "stm%?db\t");
- break;
-
- default:
- gcc_unreachable ();
- }
-
- sprintf (buf + strlen (buf), "%s%s, {%s%s", REGISTER_PREFIX,
- reg_names[base_reg], REGISTER_PREFIX, reg_names[regs[0]]);
-
- for (i = 1; i < nops; i++)
- sprintf (buf + strlen (buf), ", %s%s", REGISTER_PREFIX,
- reg_names[regs[i]]);
-
- strcat (buf, "}\t%@ phole stm");
-
- output_asm_insn (buf, operands);
- return "";
-}
-
-/* Routines for use in generating RTL. */
-
-rtx
-arm_gen_load_multiple (int base_regno, int count, rtx from, int up,
- int write_back, rtx basemem, HOST_WIDE_INT *offsetp)
-{
- HOST_WIDE_INT offset = *offsetp;
- int i = 0, j;
- rtx result;
- int sign = up ? 1 : -1;
- rtx mem, addr;
-
- /* XScale has load-store double instructions, but they have stricter
- alignment requirements than load-store multiple, so we cannot
- use them.
-
- For XScale ldm requires 2 + NREGS cycles to complete and blocks
- the pipeline until completion.
-
- NREGS CYCLES
- 1 3
- 2 4
- 3 5
- 4 6
-
- An ldr instruction takes 1-3 cycles, but does not block the
- pipeline.
-
- NREGS CYCLES
- 1 1-3
- 2 2-6
- 3 3-9
- 4 4-12
-
- Best case ldr will always win. However, the more ldr instructions
- we issue, the less likely we are to be able to schedule them well.
- Using ldr instructions also increases code size.
-
- As a compromise, we use ldr for counts of 1 or 2 regs, and ldm
- for counts of 3 or 4 regs. */
- if (arm_tune_xscale && count <= 2 && ! optimize_size)
- {
- rtx seq;
-
- start_sequence ();
-
- for (i = 0; i < count; i++)
- {
- addr = plus_constant (from, i * 4 * sign);
- mem = adjust_automodify_address (basemem, SImode, addr, offset);
- emit_move_insn (gen_rtx_REG (SImode, base_regno + i), mem);
- offset += 4 * sign;
- }
-
- if (write_back)
- {
- emit_move_insn (from, plus_constant (from, count * 4 * sign));
- *offsetp = offset;
- }
-
- seq = get_insns ();
- end_sequence ();
-
- return seq;
- }
-
- result = gen_rtx_PARALLEL (VOIDmode,
- rtvec_alloc (count + (write_back ? 1 : 0)));
- if (write_back)
- {
- XVECEXP (result, 0, 0)
- = gen_rtx_SET (VOIDmode, from, plus_constant (from, count * 4 * sign));
- i = 1;
- count++;
- }
-
- for (j = 0; i < count; i++, j++)
- {
- addr = plus_constant (from, j * 4 * sign);
- mem = adjust_automodify_address_nv (basemem, SImode, addr, offset);
- XVECEXP (result, 0, i)
- = gen_rtx_SET (VOIDmode, gen_rtx_REG (SImode, base_regno + j), mem);
- offset += 4 * sign;
- }
-
- if (write_back)
- *offsetp = offset;
-
- return result;
-}
-
-rtx
-arm_gen_store_multiple (int base_regno, int count, rtx to, int up,
- int write_back, rtx basemem, HOST_WIDE_INT *offsetp)
-{
- HOST_WIDE_INT offset = *offsetp;
- int i = 0, j;
- rtx result;
- int sign = up ? 1 : -1;
- rtx mem, addr;
-
- /* See arm_gen_load_multiple for discussion of
- the pros/cons of ldm/stm usage for XScale. */
- if (arm_tune_xscale && count <= 2 && ! optimize_size)
- {
- rtx seq;
-
- start_sequence ();
-
- for (i = 0; i < count; i++)
- {
- addr = plus_constant (to, i * 4 * sign);
- mem = adjust_automodify_address (basemem, SImode, addr, offset);
- emit_move_insn (mem, gen_rtx_REG (SImode, base_regno + i));
- offset += 4 * sign;
- }
-
- if (write_back)
- {
- emit_move_insn (to, plus_constant (to, count * 4 * sign));
- *offsetp = offset;
- }
-
- seq = get_insns ();
- end_sequence ();
-
- return seq;
- }
-
- result = gen_rtx_PARALLEL (VOIDmode,
- rtvec_alloc (count + (write_back ? 1 : 0)));
- if (write_back)
- {
- XVECEXP (result, 0, 0)
- = gen_rtx_SET (VOIDmode, to,
- plus_constant (to, count * 4 * sign));
- i = 1;
- count++;
- }
-
- for (j = 0; i < count; i++, j++)
- {
- addr = plus_constant (to, j * 4 * sign);
- mem = adjust_automodify_address_nv (basemem, SImode, addr, offset);
- XVECEXP (result, 0, i)
- = gen_rtx_SET (VOIDmode, mem, gen_rtx_REG (SImode, base_regno + j));
- offset += 4 * sign;
- }
-
- if (write_back)
- *offsetp = offset;
-
- return result;
-}
-
-int
-arm_gen_movmemqi (rtx *operands)
-{
- HOST_WIDE_INT in_words_to_go, out_words_to_go, last_bytes;
- HOST_WIDE_INT srcoffset, dstoffset;
- int i;
- rtx src, dst, srcbase, dstbase;
- rtx part_bytes_reg = NULL;
- rtx mem;
-
- if (GET_CODE (operands[2]) != CONST_INT
- || GET_CODE (operands[3]) != CONST_INT
- || INTVAL (operands[2]) > 64
- || INTVAL (operands[3]) & 3)
- return 0;
-
- dstbase = operands[0];
- srcbase = operands[1];
-
- dst = copy_to_mode_reg (SImode, XEXP (dstbase, 0));
- src = copy_to_mode_reg (SImode, XEXP (srcbase, 0));
-
- in_words_to_go = ARM_NUM_INTS (INTVAL (operands[2]));
- out_words_to_go = INTVAL (operands[2]) / 4;
- last_bytes = INTVAL (operands[2]) & 3;
- dstoffset = srcoffset = 0;
-
- if (out_words_to_go != in_words_to_go && ((in_words_to_go - 1) & 3) != 0)
- part_bytes_reg = gen_rtx_REG (SImode, (in_words_to_go - 1) & 3);
-
- for (i = 0; in_words_to_go >= 2; i+=4)
- {
- if (in_words_to_go > 4)
- emit_insn (arm_gen_load_multiple (0, 4, src, TRUE, TRUE,
- srcbase, &srcoffset));
- else
- emit_insn (arm_gen_load_multiple (0, in_words_to_go, src, TRUE,
- FALSE, srcbase, &srcoffset));
-
- if (out_words_to_go)
- {
- if (out_words_to_go > 4)
- emit_insn (arm_gen_store_multiple (0, 4, dst, TRUE, TRUE,
- dstbase, &dstoffset));
- else if (out_words_to_go != 1)
- emit_insn (arm_gen_store_multiple (0, out_words_to_go,
- dst, TRUE,
- (last_bytes == 0
- ? FALSE : TRUE),
- dstbase, &dstoffset));
- else
- {
- mem = adjust_automodify_address (dstbase, SImode, dst, dstoffset);
- emit_move_insn (mem, gen_rtx_REG (SImode, 0));
- if (last_bytes != 0)
- {
- emit_insn (gen_addsi3 (dst, dst, GEN_INT (4)));
- dstoffset += 4;
- }
- }
- }
-
- in_words_to_go -= in_words_to_go < 4 ? in_words_to_go : 4;
- out_words_to_go -= out_words_to_go < 4 ? out_words_to_go : 4;
- }
-
- /* OUT_WORDS_TO_GO will be zero here if there are byte stores to do. */
- if (out_words_to_go)
- {
- rtx sreg;
-
- mem = adjust_automodify_address (srcbase, SImode, src, srcoffset);
- sreg = copy_to_reg (mem);
-
- mem = adjust_automodify_address (dstbase, SImode, dst, dstoffset);
- emit_move_insn (mem, sreg);
- in_words_to_go--;
-
- gcc_assert (!in_words_to_go); /* Sanity check */
- }
-
- if (in_words_to_go)
- {
- gcc_assert (in_words_to_go > 0);
-
- mem = adjust_automodify_address (srcbase, SImode, src, srcoffset);
- part_bytes_reg = copy_to_mode_reg (SImode, mem);
- }
-
- gcc_assert (!last_bytes || part_bytes_reg);
-
- if (BYTES_BIG_ENDIAN && last_bytes)
- {
- rtx tmp = gen_reg_rtx (SImode);
-
- /* The bytes we want are in the top end of the word. */
- emit_insn (gen_lshrsi3 (tmp, part_bytes_reg,
- GEN_INT (8 * (4 - last_bytes))));
- part_bytes_reg = tmp;
-
- while (last_bytes)
- {
- mem = adjust_automodify_address (dstbase, QImode,
- plus_constant (dst, last_bytes - 1),
- dstoffset + last_bytes - 1);
- emit_move_insn (mem, gen_lowpart (QImode, part_bytes_reg));
-
- if (--last_bytes)
- {
- tmp = gen_reg_rtx (SImode);
- emit_insn (gen_lshrsi3 (tmp, part_bytes_reg, GEN_INT (8)));
- part_bytes_reg = tmp;
- }
- }
-
- }
- else
- {
- if (last_bytes > 1)
- {
- mem = adjust_automodify_address (dstbase, HImode, dst, dstoffset);
- emit_move_insn (mem, gen_lowpart (HImode, part_bytes_reg));
- last_bytes -= 2;
- if (last_bytes)
- {
- rtx tmp = gen_reg_rtx (SImode);
- emit_insn (gen_addsi3 (dst, dst, const2_rtx));
- emit_insn (gen_lshrsi3 (tmp, part_bytes_reg, GEN_INT (16)));
- part_bytes_reg = tmp;
- dstoffset += 2;
- }
- }
-
- if (last_bytes)
- {
- mem = adjust_automodify_address (dstbase, QImode, dst, dstoffset);
- emit_move_insn (mem, gen_lowpart (QImode, part_bytes_reg));
- }
- }
-
- return 1;
-}
-
-/* Select a dominance comparison mode if possible for a test of the general
- form (OP (COND_OR (X) (Y)) (const_int 0)). We support three forms.
- COND_OR == DOM_CC_X_AND_Y => (X && Y)
- COND_OR == DOM_CC_NX_OR_Y => ((! X) || Y)
- COND_OR == DOM_CC_X_OR_Y => (X || Y)
- In all cases OP will be either EQ or NE, but we don't need to know which
- here. If we are unable to support a dominance comparison we return
- CC mode. This will then fail to match for the RTL expressions that
- generate this call. */
-enum machine_mode
-arm_select_dominance_cc_mode (rtx x, rtx y, HOST_WIDE_INT cond_or)
-{
- enum rtx_code cond1, cond2;
- int swapped = 0;
-
- /* Currently we will probably get the wrong result if the individual
- comparisons are not simple. This also ensures that it is safe to
- reverse a comparison if necessary. */
- if ((arm_select_cc_mode (cond1 = GET_CODE (x), XEXP (x, 0), XEXP (x, 1))
- != CCmode)
- || (arm_select_cc_mode (cond2 = GET_CODE (y), XEXP (y, 0), XEXP (y, 1))
- != CCmode))
- return CCmode;
-
- /* The if_then_else variant of this tests the second condition if the
- first passes, but is true if the first fails. Reverse the first
- condition to get a true "inclusive-or" expression. */
- if (cond_or == DOM_CC_NX_OR_Y)
- cond1 = reverse_condition (cond1);
-
- /* If the comparisons are not equal, and one doesn't dominate the other,
- then we can't do this. */
- if (cond1 != cond2
- && !comparison_dominates_p (cond1, cond2)
- && (swapped = 1, !comparison_dominates_p (cond2, cond1)))
- return CCmode;
-
- if (swapped)
- {
- enum rtx_code temp = cond1;
- cond1 = cond2;
- cond2 = temp;
- }
-
- switch (cond1)
- {
- case EQ:
- if (cond_or == DOM_CC_X_AND_Y)
- return CC_DEQmode;
-
- switch (cond2)
- {
- case EQ: return CC_DEQmode;
- case LE: return CC_DLEmode;
- case LEU: return CC_DLEUmode;
- case GE: return CC_DGEmode;
- case GEU: return CC_DGEUmode;
- default: gcc_unreachable ();
- }
-
- case LT:
- if (cond_or == DOM_CC_X_AND_Y)
- return CC_DLTmode;
-
- switch (cond2)
- {
- case LT:
- return CC_DLTmode;
- case LE:
- return CC_DLEmode;
- case NE:
- return CC_DNEmode;
- default:
- gcc_unreachable ();
- }
-
- case GT:
- if (cond_or == DOM_CC_X_AND_Y)
- return CC_DGTmode;
-
- switch (cond2)
- {
- case GT:
- return CC_DGTmode;
- case GE:
- return CC_DGEmode;
- case NE:
- return CC_DNEmode;
- default:
- gcc_unreachable ();
- }
-
- case LTU:
- if (cond_or == DOM_CC_X_AND_Y)
- return CC_DLTUmode;
-
- switch (cond2)
- {
- case LTU:
- return CC_DLTUmode;
- case LEU:
- return CC_DLEUmode;
- case NE:
- return CC_DNEmode;
- default:
- gcc_unreachable ();
- }
-
- case GTU:
- if (cond_or == DOM_CC_X_AND_Y)
- return CC_DGTUmode;
-
- switch (cond2)
- {
- case GTU:
- return CC_DGTUmode;
- case GEU:
- return CC_DGEUmode;
- case NE:
- return CC_DNEmode;
- default:
- gcc_unreachable ();
- }
-
- /* The remaining cases only occur when both comparisons are the
- same. */
- case NE:
- gcc_assert (cond1 == cond2);
- return CC_DNEmode;
-
- case LE:
- gcc_assert (cond1 == cond2);
- return CC_DLEmode;
-
- case GE:
- gcc_assert (cond1 == cond2);
- return CC_DGEmode;
-
- case LEU:
- gcc_assert (cond1 == cond2);
- return CC_DLEUmode;
-
- case GEU:
- gcc_assert (cond1 == cond2);
- return CC_DGEUmode;
-
- default:
- gcc_unreachable ();
- }
-}
-
-enum machine_mode
-arm_select_cc_mode (enum rtx_code op, rtx x, rtx y)
-{
- /* All floating point compares return CCFP if it is an equality
- comparison, and CCFPE otherwise. */
- if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
- {
- switch (op)
- {
- case EQ:
- case NE:
- case UNORDERED:
- case ORDERED:
- case UNLT:
- case UNLE:
- case UNGT:
- case UNGE:
- case UNEQ:
- case LTGT:
- return CCFPmode;
-
- case LT:
- case LE:
- case GT:
- case GE:
- if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
- return CCFPmode;
- return CCFPEmode;
-
- default:
- gcc_unreachable ();
- }
- }
-
- /* A compare with a shifted operand. Because of canonicalization, the
- comparison will have to be swapped when we emit the assembler. */
- if (GET_MODE (y) == SImode && GET_CODE (y) == REG
- && (GET_CODE (x) == ASHIFT || GET_CODE (x) == ASHIFTRT
- || GET_CODE (x) == LSHIFTRT || GET_CODE (x) == ROTATE
- || GET_CODE (x) == ROTATERT))
- return CC_SWPmode;
-
- /* This operation is performed swapped, but since we only rely on the Z
- flag we don't need an additional mode. */
- if (GET_MODE (y) == SImode && REG_P (y)
- && GET_CODE (x) == NEG
- && (op == EQ || op == NE))
- return CC_Zmode;
-
- /* This is a special case that is used by combine to allow a
- comparison of a shifted byte load to be split into a zero-extend
- followed by a comparison of the shifted integer (only valid for
- equalities and unsigned inequalities). */
- if (GET_MODE (x) == SImode
- && GET_CODE (x) == ASHIFT
- && GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) == 24
- && GET_CODE (XEXP (x, 0)) == SUBREG
- && GET_CODE (SUBREG_REG (XEXP (x, 0))) == MEM
- && GET_MODE (SUBREG_REG (XEXP (x, 0))) == QImode
- && (op == EQ || op == NE
- || op == GEU || op == GTU || op == LTU || op == LEU)
- && GET_CODE (y) == CONST_INT)
- return CC_Zmode;
-
- /* A construct for a conditional compare, if the false arm contains
- 0, then both conditions must be true, otherwise either condition
- must be true. Not all conditions are possible, so CCmode is
- returned if it can't be done. */
- if (GET_CODE (x) == IF_THEN_ELSE
- && (XEXP (x, 2) == const0_rtx
- || XEXP (x, 2) == const1_rtx)
- && COMPARISON_P (XEXP (x, 0))
- && COMPARISON_P (XEXP (x, 1)))
- return arm_select_dominance_cc_mode (XEXP (x, 0), XEXP (x, 1),
- INTVAL (XEXP (x, 2)));
-
- /* Alternate canonicalizations of the above. These are somewhat cleaner. */
- if (GET_CODE (x) == AND
- && COMPARISON_P (XEXP (x, 0))
- && COMPARISON_P (XEXP (x, 1)))
- return arm_select_dominance_cc_mode (XEXP (x, 0), XEXP (x, 1),
- DOM_CC_X_AND_Y);
-
- if (GET_CODE (x) == IOR
- && COMPARISON_P (XEXP (x, 0))
- && COMPARISON_P (XEXP (x, 1)))
- return arm_select_dominance_cc_mode (XEXP (x, 0), XEXP (x, 1),
- DOM_CC_X_OR_Y);
-
- /* An operation (on Thumb) where we want to test for a single bit.
- This is done by shifting that bit up into the top bit of a
- scratch register; we can then branch on the sign bit. */
- if (TARGET_THUMB
- && GET_MODE (x) == SImode
- && (op == EQ || op == NE)
- && GET_CODE (x) == ZERO_EXTRACT
- && XEXP (x, 1) == const1_rtx)
- return CC_Nmode;
-
- /* An operation that sets the condition codes as a side-effect, the
- V flag is not set correctly, so we can only use comparisons where
- this doesn't matter. (For LT and GE we can use "mi" and "pl"
- instead.) */
- if (GET_MODE (x) == SImode
- && y == const0_rtx
- && (op == EQ || op == NE || op == LT || op == GE)
- && (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
- || GET_CODE (x) == AND || GET_CODE (x) == IOR
- || GET_CODE (x) == XOR || GET_CODE (x) == MULT
- || GET_CODE (x) == NOT || GET_CODE (x) == NEG
- || GET_CODE (x) == LSHIFTRT
- || GET_CODE (x) == ASHIFT || GET_CODE (x) == ASHIFTRT
- || GET_CODE (x) == ROTATERT
- || (TARGET_ARM && GET_CODE (x) == ZERO_EXTRACT)))
- return CC_NOOVmode;
-
- if (GET_MODE (x) == QImode && (op == EQ || op == NE))
- return CC_Zmode;
-
- if (GET_MODE (x) == SImode && (op == LTU || op == GEU)
- && GET_CODE (x) == PLUS
- && (rtx_equal_p (XEXP (x, 0), y) || rtx_equal_p (XEXP (x, 1), y)))
- return CC_Cmode;
-
- return CCmode;
-}
-
-/* X and Y are two things to compare using CODE. Emit the compare insn and
- return the rtx for register 0 in the proper mode. FP means this is a
- floating point compare: I don't think that it is needed on the arm. */
-rtx
-arm_gen_compare_reg (enum rtx_code code, rtx x, rtx y)
-{
- enum machine_mode mode = SELECT_CC_MODE (code, x, y);
- rtx cc_reg = gen_rtx_REG (mode, CC_REGNUM);
-
- emit_set_insn (cc_reg, gen_rtx_COMPARE (mode, x, y));
-
- return cc_reg;
-}
-
-/* Generate a sequence of insns that will generate the correct return
- address mask depending on the physical architecture that the program
- is running on. */
-rtx
-arm_gen_return_addr_mask (void)
-{
- rtx reg = gen_reg_rtx (Pmode);
-
- emit_insn (gen_return_addr_mask (reg));
- return reg;
-}
-
-void
-arm_reload_in_hi (rtx *operands)
-{
- rtx ref = operands[1];
- rtx base, scratch;
- HOST_WIDE_INT offset = 0;
-
- if (GET_CODE (ref) == SUBREG)
- {
- offset = SUBREG_BYTE (ref);
- ref = SUBREG_REG (ref);
- }
-
- if (GET_CODE (ref) == REG)
- {
- /* We have a pseudo which has been spilt onto the stack; there
- are two cases here: the first where there is a simple
- stack-slot replacement and a second where the stack-slot is
- out of range, or is used as a subreg. */
- if (reg_equiv_mem[REGNO (ref)])
- {
- ref = reg_equiv_mem[REGNO (ref)];
- base = find_replacement (&XEXP (ref, 0));
- }
- else
- /* The slot is out of range, or was dressed up in a SUBREG. */
- base = reg_equiv_address[REGNO (ref)];
- }
- else
- base = find_replacement (&XEXP (ref, 0));
-
- /* Handle the case where the address is too complex to be offset by 1. */
- if (GET_CODE (base) == MINUS
- || (GET_CODE (base) == PLUS && GET_CODE (XEXP (base, 1)) != CONST_INT))
- {
- rtx base_plus = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
-
- emit_set_insn (base_plus, base);
- base = base_plus;
- }
- else if (GET_CODE (base) == PLUS)
- {
- /* The addend must be CONST_INT, or we would have dealt with it above. */
- HOST_WIDE_INT hi, lo;
-
- offset += INTVAL (XEXP (base, 1));
- base = XEXP (base, 0);
-
- /* Rework the address into a legal sequence of insns. */
- /* Valid range for lo is -4095 -> 4095 */
- lo = (offset >= 0
- ? (offset & 0xfff)
- : -((-offset) & 0xfff));
-
- /* Corner case, if lo is the max offset then we would be out of range
- once we have added the additional 1 below, so bump the msb into the
- pre-loading insn(s). */
- if (lo == 4095)
- lo &= 0x7ff;
-
- hi = ((((offset - lo) & (HOST_WIDE_INT) 0xffffffff)
- ^ (HOST_WIDE_INT) 0x80000000)
- - (HOST_WIDE_INT) 0x80000000);
-
- gcc_assert (hi + lo == offset);
-
- if (hi != 0)
- {
- rtx base_plus = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
-
- /* Get the base address; addsi3 knows how to handle constants
- that require more than one insn. */
- emit_insn (gen_addsi3 (base_plus, base, GEN_INT (hi)));
- base = base_plus;
- offset = lo;
- }
- }
-
- /* Operands[2] may overlap operands[0] (though it won't overlap
- operands[1]), that's why we asked for a DImode reg -- so we can
- use the bit that does not overlap. */
- if (REGNO (operands[2]) == REGNO (operands[0]))
- scratch = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
- else
- scratch = gen_rtx_REG (SImode, REGNO (operands[2]));
-
- emit_insn (gen_zero_extendqisi2 (scratch,
- gen_rtx_MEM (QImode,
- plus_constant (base,
- offset))));
- emit_insn (gen_zero_extendqisi2 (gen_rtx_SUBREG (SImode, operands[0], 0),
- gen_rtx_MEM (QImode,
- plus_constant (base,
- offset + 1))));
- if (!BYTES_BIG_ENDIAN)
- emit_set_insn (gen_rtx_SUBREG (SImode, operands[0], 0),
- gen_rtx_IOR (SImode,
- gen_rtx_ASHIFT
- (SImode,
- gen_rtx_SUBREG (SImode, operands[0], 0),
- GEN_INT (8)),
- scratch));
- else
- emit_set_insn (gen_rtx_SUBREG (SImode, operands[0], 0),
- gen_rtx_IOR (SImode,
- gen_rtx_ASHIFT (SImode, scratch,
- GEN_INT (8)),
- gen_rtx_SUBREG (SImode, operands[0], 0)));
-}
-
-/* Handle storing a half-word to memory during reload by synthesizing as two
- byte stores. Take care not to clobber the input values until after we
- have moved them somewhere safe. This code assumes that if the DImode
- scratch in operands[2] overlaps either the input value or output address
- in some way, then that value must die in this insn (we absolutely need
- two scratch registers for some corner cases). */
-void
-arm_reload_out_hi (rtx *operands)
-{
- rtx ref = operands[0];
- rtx outval = operands[1];
- rtx base, scratch;
- HOST_WIDE_INT offset = 0;
-
- if (GET_CODE (ref) == SUBREG)
- {
- offset = SUBREG_BYTE (ref);
- ref = SUBREG_REG (ref);
- }
-
- if (GET_CODE (ref) == REG)
- {
- /* We have a pseudo which has been spilt onto the stack; there
- are two cases here: the first where there is a simple
- stack-slot replacement and a second where the stack-slot is
- out of range, or is used as a subreg. */
- if (reg_equiv_mem[REGNO (ref)])
- {
- ref = reg_equiv_mem[REGNO (ref)];
- base = find_replacement (&XEXP (ref, 0));
- }
- else
- /* The slot is out of range, or was dressed up in a SUBREG. */
- base = reg_equiv_address[REGNO (ref)];
- }
- else
- base = find_replacement (&XEXP (ref, 0));
-
- scratch = gen_rtx_REG (SImode, REGNO (operands[2]));
-
- /* Handle the case where the address is too complex to be offset by 1. */
- if (GET_CODE (base) == MINUS
- || (GET_CODE (base) == PLUS && GET_CODE (XEXP (base, 1)) != CONST_INT))
- {
- rtx base_plus = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
-
- /* Be careful not to destroy OUTVAL. */
- if (reg_overlap_mentioned_p (base_plus, outval))
- {
- /* Updating base_plus might destroy outval, see if we can
- swap the scratch and base_plus. */
- if (!reg_overlap_mentioned_p (scratch, outval))
- {
- rtx tmp = scratch;
- scratch = base_plus;
- base_plus = tmp;
- }
- else
- {
- rtx scratch_hi = gen_rtx_REG (HImode, REGNO (operands[2]));
-
- /* Be conservative and copy OUTVAL into the scratch now,
- this should only be necessary if outval is a subreg
- of something larger than a word. */
- /* XXX Might this clobber base? I can't see how it can,
- since scratch is known to overlap with OUTVAL, and
- must be wider than a word. */
- emit_insn (gen_movhi (scratch_hi, outval));
- outval = scratch_hi;
- }
- }
-
- emit_set_insn (base_plus, base);
- base = base_plus;
- }
- else if (GET_CODE (base) == PLUS)
- {
- /* The addend must be CONST_INT, or we would have dealt with it above. */
- HOST_WIDE_INT hi, lo;
-
- offset += INTVAL (XEXP (base, 1));
- base = XEXP (base, 0);
-
- /* Rework the address into a legal sequence of insns. */
- /* Valid range for lo is -4095 -> 4095 */
- lo = (offset >= 0
- ? (offset & 0xfff)
- : -((-offset) & 0xfff));
-
- /* Corner case, if lo is the max offset then we would be out of range
- once we have added the additional 1 below, so bump the msb into the
- pre-loading insn(s). */
- if (lo == 4095)
- lo &= 0x7ff;
-
- hi = ((((offset - lo) & (HOST_WIDE_INT) 0xffffffff)
- ^ (HOST_WIDE_INT) 0x80000000)
- - (HOST_WIDE_INT) 0x80000000);
-
- gcc_assert (hi + lo == offset);
-
- if (hi != 0)
- {
- rtx base_plus = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
-
- /* Be careful not to destroy OUTVAL. */
- if (reg_overlap_mentioned_p (base_plus, outval))
- {
- /* Updating base_plus might destroy outval, see if we
- can swap the scratch and base_plus. */
- if (!reg_overlap_mentioned_p (scratch, outval))
- {
- rtx tmp = scratch;
- scratch = base_plus;
- base_plus = tmp;
- }
- else
- {
- rtx scratch_hi = gen_rtx_REG (HImode, REGNO (operands[2]));
-
- /* Be conservative and copy outval into scratch now,
- this should only be necessary if outval is a
- subreg of something larger than a word. */
- /* XXX Might this clobber base? I can't see how it
- can, since scratch is known to overlap with
- outval. */
- emit_insn (gen_movhi (scratch_hi, outval));
- outval = scratch_hi;
- }
- }
-
- /* Get the base address; addsi3 knows how to handle constants
- that require more than one insn. */
- emit_insn (gen_addsi3 (base_plus, base, GEN_INT (hi)));
- base = base_plus;
- offset = lo;
- }
- }
-
- if (BYTES_BIG_ENDIAN)
- {
- emit_insn (gen_movqi (gen_rtx_MEM (QImode,
- plus_constant (base, offset + 1)),
- gen_lowpart (QImode, outval)));
- emit_insn (gen_lshrsi3 (scratch,
- gen_rtx_SUBREG (SImode, outval, 0),
- GEN_INT (8)));
- emit_insn (gen_movqi (gen_rtx_MEM (QImode, plus_constant (base, offset)),
- gen_lowpart (QImode, scratch)));
- }
- else
- {
- emit_insn (gen_movqi (gen_rtx_MEM (QImode, plus_constant (base, offset)),
- gen_lowpart (QImode, outval)));
- emit_insn (gen_lshrsi3 (scratch,
- gen_rtx_SUBREG (SImode, outval, 0),
- GEN_INT (8)));
- emit_insn (gen_movqi (gen_rtx_MEM (QImode,
- plus_constant (base, offset + 1)),
- gen_lowpart (QImode, scratch)));
- }
-}
-
-/* Return true if a type must be passed in memory. For AAPCS, small aggregates
- (padded to the size of a word) should be passed in a register. */
-
-static bool
-arm_must_pass_in_stack (enum machine_mode mode, tree type)
-{
- if (TARGET_AAPCS_BASED)
- return must_pass_in_stack_var_size (mode, type);
- else
- return must_pass_in_stack_var_size_or_pad (mode, type);
-}
-
-
-/* For use by FUNCTION_ARG_PADDING (MODE, TYPE).
- Return true if an argument passed on the stack should be padded upwards,
- i.e. if the least-significant byte has useful data.
- For legacy APCS ABIs we use the default. For AAPCS based ABIs small
- aggregate types are placed in the lowest memory address. */
-
-bool
-arm_pad_arg_upward (enum machine_mode mode, tree type)
-{
- if (!TARGET_AAPCS_BASED)
- return DEFAULT_FUNCTION_ARG_PADDING(mode, type) == upward;
-
- if (type && BYTES_BIG_ENDIAN && INTEGRAL_TYPE_P (type))
- return false;
-
- return true;
-}
-
-
-/* Similarly, for use by BLOCK_REG_PADDING (MODE, TYPE, FIRST).
- For non-AAPCS, return !BYTES_BIG_ENDIAN if the least significant
- byte of the register has useful data, and return the opposite if the
- most significant byte does.
- For AAPCS, small aggregates and small complex types are always padded
- upwards. */
-
-bool
-arm_pad_reg_upward (enum machine_mode mode ATTRIBUTE_UNUSED,
- tree type, int first ATTRIBUTE_UNUSED)
-{
- if (TARGET_AAPCS_BASED
- && BYTES_BIG_ENDIAN
- && (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == COMPLEX_TYPE)
- && int_size_in_bytes (type) <= 4)
- return true;
-
- /* Otherwise, use default padding. */
- return !BYTES_BIG_ENDIAN;
-}
-
-
-/* Print a symbolic form of X to the debug file, F. */
-static void
-arm_print_value (FILE *f, rtx x)
-{
- switch (GET_CODE (x))
- {
- case CONST_INT:
- fprintf (f, HOST_WIDE_INT_PRINT_HEX, INTVAL (x));
- return;
-
- case CONST_DOUBLE:
- fprintf (f, "<0x%lx,0x%lx>", (long)XWINT (x, 2), (long)XWINT (x, 3));
- return;
-
- case CONST_VECTOR:
- {
- int i;
-
- fprintf (f, "<");
- for (i = 0; i < CONST_VECTOR_NUNITS (x); i++)
- {
- fprintf (f, HOST_WIDE_INT_PRINT_HEX, INTVAL (CONST_VECTOR_ELT (x, i)));
- if (i < (CONST_VECTOR_NUNITS (x) - 1))
- fputc (',', f);
- }
- fprintf (f, ">");
- }
- return;
-
- case CONST_STRING:
- fprintf (f, "\"%s\"", XSTR (x, 0));
- return;
-
- case SYMBOL_REF:
- fprintf (f, "`%s'", XSTR (x, 0));
- return;
-
- case LABEL_REF:
- fprintf (f, "L%d", INSN_UID (XEXP (x, 0)));
- return;
-
- case CONST:
- arm_print_value (f, XEXP (x, 0));
- return;
-
- case PLUS:
- arm_print_value (f, XEXP (x, 0));
- fprintf (f, "+");
- arm_print_value (f, XEXP (x, 1));
- return;
-
- case PC:
- fprintf (f, "pc");
- return;
-
- default:
- fprintf (f, "????");
- return;
- }
-}
-
-/* Routines for manipulation of the constant pool. */
-
-/* Arm instructions cannot load a large constant directly into a
- register; they have to come from a pc relative load. The constant
- must therefore be placed in the addressable range of the pc
- relative load. Depending on the precise pc relative load
- instruction the range is somewhere between 256 bytes and 4k. 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 the code larger.
-
- Normally we can hide the table after an existing unconditional
- branch so that there is no interruption of the flow, but in the
- worst case the code looks like this:
-
- 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 after scheduling, which notices
- which instructions need to have their operands fetched from the
- constant table and builds the table.
-
- The algorithm starts by building a table of all the constants that
- need fixing up and all the natural barriers in the function (places
- where a constant table can be dropped without breaking the flow).
- For each fixup we note how far the pc-relative replacement will be
- able to reach and the offset of the instruction into the function.
-
- Having built the table we then group the fixes together to form
- tables that are as large as possible (subject to addressing
- constraints) and emit each table of constants after the last
- barrier that is within range of all the instructions in the group.
- If a group does not contain a barrier, then we forcibly create one
- by inserting a jump instruction into the flow. Once the table has
- been inserted, the insns are then modified to reference the
- relevant entry in the pool.
-
- Possible enhancements to the algorithm (not implemented) are:
-
- 1) For some processors and object formats, there may be benefit in
- aligning the pools to the start of cache lines; this alignment
- would need to be taken into account when calculating addressability
- of a pool. */
-
-/* These typedefs are located at the start of this file, so that
- they can be used in the prototypes there. This comment is to
- remind readers of that fact so that the following structures
- can be understood more easily.
-
- typedef struct minipool_node Mnode;
- typedef struct minipool_fixup Mfix; */
-
-struct minipool_node
-{
- /* Doubly linked chain of entries. */
- Mnode * next;
- Mnode * prev;
- /* The maximum offset into the code that this entry can be placed. While
- pushing fixes for forward references, all entries are sorted in order
- of increasing max_address. */
- HOST_WIDE_INT max_address;
- /* Similarly for an entry inserted for a backwards ref. */
- HOST_WIDE_INT min_address;
- /* The number of fixes referencing this entry. This can become zero
- if we "unpush" an entry. In this case we ignore the entry when we
- come to emit the code. */
- int refcount;
- /* The offset from the start of the minipool. */
- HOST_WIDE_INT offset;
- /* The value in table. */
- rtx value;
- /* The mode of value. */
- enum machine_mode mode;
- /* The size of the value. With iWMMXt enabled
- sizes > 4 also imply an alignment of 8-bytes. */
- int fix_size;
-};
-
-struct minipool_fixup
-{
- Mfix * next;
- rtx insn;
- HOST_WIDE_INT address;
- rtx * loc;
- enum machine_mode mode;
- int fix_size;
- rtx value;
- Mnode * minipool;
- HOST_WIDE_INT forwards;
- HOST_WIDE_INT backwards;
-};
-
-/* Fixes less than a word need padding out to a word boundary. */
-#define MINIPOOL_FIX_SIZE(mode) \
- (GET_MODE_SIZE ((mode)) >= 4 ? GET_MODE_SIZE ((mode)) : 4)
-
-static Mnode * minipool_vector_head;
-static Mnode * minipool_vector_tail;
-static rtx minipool_vector_label;
-static int minipool_pad;
-
-/* The linked list of all minipool fixes required for this function. */
-Mfix * minipool_fix_head;
-Mfix * minipool_fix_tail;
-/* The fix entry for the current minipool, once it has been placed. */
-Mfix * minipool_barrier;
-
-/* Determines if INSN is the start of a jump table. Returns the end
- of the TABLE or NULL_RTX. */
-static rtx
-is_jump_table (rtx insn)
-{
- rtx table;
-
- if (GET_CODE (insn) == JUMP_INSN
- && JUMP_LABEL (insn) != NULL
- && ((table = next_real_insn (JUMP_LABEL (insn)))
- == next_real_insn (insn))
- && table != NULL
- && GET_CODE (table) == JUMP_INSN
- && (GET_CODE (PATTERN (table)) == ADDR_VEC
- || GET_CODE (PATTERN (table)) == ADDR_DIFF_VEC))
- return table;
-
- return NULL_RTX;
-}
-
-#ifndef JUMP_TABLES_IN_TEXT_SECTION
-#define JUMP_TABLES_IN_TEXT_SECTION 0
-#endif
-
-static HOST_WIDE_INT
-get_jump_table_size (rtx insn)
-{
- /* ADDR_VECs only take room if read-only data does into the text
- section. */
- if (JUMP_TABLES_IN_TEXT_SECTION || readonly_data_section == text_section)
- {
- rtx body = PATTERN (insn);
- int elt = GET_CODE (body) == ADDR_DIFF_VEC ? 1 : 0;
-
- return GET_MODE_SIZE (GET_MODE (body)) * XVECLEN (body, elt);
- }
-
- return 0;
-}
-
-/* Move a minipool fix MP from its current location to before MAX_MP.
- If MAX_MP is NULL, then MP doesn't need moving, but the addressing
- constraints may need updating. */
-static Mnode *
-move_minipool_fix_forward_ref (Mnode *mp, Mnode *max_mp,
- HOST_WIDE_INT max_address)
-{
- /* The code below assumes these are different. */
- gcc_assert (mp != max_mp);
-
- if (max_mp == NULL)
- {
- if (max_address < mp->max_address)
- mp->max_address = max_address;
- }
- else
- {
- if (max_address > max_mp->max_address - mp->fix_size)
- mp->max_address = max_mp->max_address - mp->fix_size;
- else
- mp->max_address = max_address;
-
- /* Unlink MP from its current position. Since max_mp is non-null,
- mp->prev must be non-null. */
- mp->prev->next = mp->next;
- if (mp->next != NULL)
- mp->next->prev = mp->prev;
- else
- minipool_vector_tail = mp->prev;
-
- /* Re-insert it before MAX_MP. */
- mp->next = max_mp;
- mp->prev = max_mp->prev;
- max_mp->prev = mp;
-
- if (mp->prev != NULL)
- mp->prev->next = mp;
- else
- minipool_vector_head = mp;
- }
-
- /* Save the new entry. */
- max_mp = mp;
-
- /* Scan over the preceding entries and adjust their addresses as
- required. */
- while (mp->prev != NULL
- && mp->prev->max_address > mp->max_address - mp->prev->fix_size)
- {
- mp->prev->max_address = mp->max_address - mp->prev->fix_size;
- mp = mp->prev;
- }
-
- return max_mp;
-}
-
-/* Add a constant to the minipool for a forward reference. Returns the
- node added or NULL if the constant will not fit in this pool. */
-static Mnode *
-add_minipool_forward_ref (Mfix *fix)
-{
- /* If set, max_mp is the first pool_entry that has a lower
- constraint than the one we are trying to add. */
- Mnode * max_mp = NULL;
- HOST_WIDE_INT max_address = fix->address + fix->forwards - minipool_pad;
- Mnode * mp;
-
- /* If the minipool starts before the end of FIX->INSN then this FIX
- can not be placed into the current pool. Furthermore, adding the
- new constant pool entry may cause the pool to start FIX_SIZE bytes
- earlier. */
- if (minipool_vector_head &&
- (fix->address + get_attr_length (fix->insn)
- >= minipool_vector_head->max_address - fix->fix_size))
- return NULL;
-
- /* Scan the pool to see if a constant with the same value has
- already been added. While we are doing this, also note the
- location where we must insert the constant if it doesn't already
- exist. */
- for (mp = minipool_vector_head; mp != NULL; mp = mp->next)
- {
- if (GET_CODE (fix->value) == GET_CODE (mp->value)
- && fix->mode == mp->mode
- && (GET_CODE (fix->value) != CODE_LABEL
- || (CODE_LABEL_NUMBER (fix->value)
- == CODE_LABEL_NUMBER (mp->value)))
- && rtx_equal_p (fix->value, mp->value))
- {
- /* More than one fix references this entry. */
- mp->refcount++;
- return move_minipool_fix_forward_ref (mp, max_mp, max_address);
- }
-
- /* Note the insertion point if necessary. */
- if (max_mp == NULL
- && mp->max_address > max_address)
- max_mp = mp;
-
- /* If we are inserting an 8-bytes aligned quantity and
- we have not already found an insertion point, then
- make sure that all such 8-byte aligned quantities are
- placed at the start of the pool. */
- if (ARM_DOUBLEWORD_ALIGN
- && max_mp == NULL
- && fix->fix_size == 8
- && mp->fix_size != 8)
- {
- max_mp = mp;
- max_address = mp->max_address;
- }
- }
-
- /* The value is not currently in the minipool, so we need to create
- a new entry for it. If MAX_MP is NULL, the entry will be put on
- the end of the list since the placement is less constrained than
- any existing entry. Otherwise, we insert the new fix before
- MAX_MP and, if necessary, adjust the constraints on the other
- entries. */
- mp = XNEW (Mnode);
- mp->fix_size = fix->fix_size;
- mp->mode = fix->mode;
- mp->value = fix->value;
- mp->refcount = 1;
- /* Not yet required for a backwards ref. */
- mp->min_address = -65536;
-
- if (max_mp == NULL)
- {
- mp->max_address = max_address;
- mp->next = NULL;
- mp->prev = minipool_vector_tail;
-
- if (mp->prev == NULL)
- {
- minipool_vector_head = mp;
- minipool_vector_label = gen_label_rtx ();
- }
- else
- mp->prev->next = mp;
-
- minipool_vector_tail = mp;
- }
- else
- {
- if (max_address > max_mp->max_address - mp->fix_size)
- mp->max_address = max_mp->max_address - mp->fix_size;
- else
- mp->max_address = max_address;
-
- mp->next = max_mp;
- mp->prev = max_mp->prev;
- max_mp->prev = mp;
- if (mp->prev != NULL)
- mp->prev->next = mp;
- else
- minipool_vector_head = mp;
- }
-
- /* Save the new entry. */
- max_mp = mp;
-
- /* Scan over the preceding entries and adjust their addresses as
- required. */
- while (mp->prev != NULL
- && mp->prev->max_address > mp->max_address - mp->prev->fix_size)
- {
- mp->prev->max_address = mp->max_address - mp->prev->fix_size;
- mp = mp->prev;
- }
-
- return max_mp;
-}
-
-static Mnode *
-move_minipool_fix_backward_ref (Mnode *mp, Mnode *min_mp,
- HOST_WIDE_INT min_address)
-{
- HOST_WIDE_INT offset;
-
- /* The code below assumes these are different. */
- gcc_assert (mp != min_mp);
-
- if (min_mp == NULL)
- {
- if (min_address > mp->min_address)
- mp->min_address = min_address;
- }
- else
- {
- /* We will adjust this below if it is too loose. */
- mp->min_address = min_address;
-
- /* Unlink MP from its current position. Since min_mp is non-null,
- mp->next must be non-null. */
- mp->next->prev = mp->prev;
- if (mp->prev != NULL)
- mp->prev->next = mp->next;
- else
- minipool_vector_head = mp->next;
-
- /* Reinsert it after MIN_MP. */
- mp->prev = min_mp;
- mp->next = min_mp->next;
- min_mp->next = mp;
- if (mp->next != NULL)
- mp->next->prev = mp;
- else
- minipool_vector_tail = mp;
- }
-
- min_mp = mp;
-
- offset = 0;
- for (mp = minipool_vector_head; mp != NULL; mp = mp->next)
- {
- mp->offset = offset;
- if (mp->refcount > 0)
- offset += mp->fix_size;
-
- if (mp->next && mp->next->min_address < mp->min_address + mp->fix_size)
- mp->next->min_address = mp->min_address + mp->fix_size;
- }
-
- return min_mp;
-}
-
-/* Add a constant to the minipool for a backward reference. Returns the
- node added or NULL if the constant will not fit in this pool.
-
- Note that the code for insertion for a backwards reference can be
- somewhat confusing because the calculated offsets for each fix do
- not take into account the size of the pool (which is still under
- construction. */
-static Mnode *
-add_minipool_backward_ref (Mfix *fix)
-{
- /* If set, min_mp is the last pool_entry that has a lower constraint
- than the one we are trying to add. */
- Mnode *min_mp = NULL;
- /* This can be negative, since it is only a constraint. */
- HOST_WIDE_INT min_address = fix->address - fix->backwards;
- Mnode *mp;
-
- /* If we can't reach the current pool from this insn, or if we can't
- insert this entry at the end of the pool without pushing other
- fixes out of range, then we don't try. This ensures that we
- can't fail later on. */
- if (min_address >= minipool_barrier->address
- || (minipool_vector_tail->min_address + fix->fix_size
- >= minipool_barrier->address))
- return NULL;
-
- /* Scan the pool to see if a constant with the same value has
- already been added. While we are doing this, also note the
- location where we must insert the constant if it doesn't already
- exist. */
- for (mp = minipool_vector_tail; mp != NULL; mp = mp->prev)
- {
- if (GET_CODE (fix->value) == GET_CODE (mp->value)
- && fix->mode == mp->mode
- && (GET_CODE (fix->value) != CODE_LABEL
- || (CODE_LABEL_NUMBER (fix->value)
- == CODE_LABEL_NUMBER (mp->value)))
- && rtx_equal_p (fix->value, mp->value)
- /* Check that there is enough slack to move this entry to the
- end of the table (this is conservative). */
- && (mp->max_address
- > (minipool_barrier->address
- + minipool_vector_tail->offset
- + minipool_vector_tail->fix_size)))
- {
- mp->refcount++;
- return move_minipool_fix_backward_ref (mp, min_mp, min_address);
- }
-
- if (min_mp != NULL)
- mp->min_address += fix->fix_size;
- else
- {
- /* Note the insertion point if necessary. */
- if (mp->min_address < min_address)
- {
- /* For now, we do not allow the insertion of 8-byte alignment
- requiring nodes anywhere but at the start of the pool. */
- if (ARM_DOUBLEWORD_ALIGN
- && fix->fix_size == 8 && mp->fix_size != 8)
- return NULL;
- else
- min_mp = mp;
- }
- else if (mp->max_address
- < minipool_barrier->address + mp->offset + fix->fix_size)
- {
- /* Inserting before this entry would push the fix beyond
- its maximum address (which can happen if we have
- re-located a forwards fix); force the new fix to come
- after it. */
- min_mp = mp;
- min_address = mp->min_address + fix->fix_size;
- }
- /* If we are inserting an 8-bytes aligned quantity and
- we have not already found an insertion point, then
- make sure that all such 8-byte aligned quantities are
- placed at the start of the pool. */
- else if (ARM_DOUBLEWORD_ALIGN
- && min_mp == NULL
- && fix->fix_size == 8
- && mp->fix_size < 8)
- {
- min_mp = mp;
- min_address = mp->min_address + fix->fix_size;
- }
- }
- }
-
- /* We need to create a new entry. */
- mp = XNEW (Mnode);
- mp->fix_size = fix->fix_size;
- mp->mode = fix->mode;
- mp->value = fix->value;
- mp->refcount = 1;
- mp->max_address = minipool_barrier->address + 65536;
-
- mp->min_address = min_address;
-
- if (min_mp == NULL)
- {
- mp->prev = NULL;
- mp->next = minipool_vector_head;
-
- if (mp->next == NULL)
- {
- minipool_vector_tail = mp;
- minipool_vector_label = gen_label_rtx ();
- }
- else
- mp->next->prev = mp;
-
- minipool_vector_head = mp;
- }
- else
- {
- mp->next = min_mp->next;
- mp->prev = min_mp;
- min_mp->next = mp;
-
- if (mp->next != NULL)
- mp->next->prev = mp;
- else
- minipool_vector_tail = mp;
- }
-
- /* Save the new entry. */
- min_mp = mp;
-
- if (mp->prev)
- mp = mp->prev;
- else
- mp->offset = 0;
-
- /* Scan over the following entries and adjust their offsets. */
- while (mp->next != NULL)
- {
- if (mp->next->min_address < mp->min_address + mp->fix_size)
- mp->next->min_address = mp->min_address + mp->fix_size;
-
- if (mp->refcount)
- mp->next->offset = mp->offset + mp->fix_size;
- else
- mp->next->offset = mp->offset;
-
- mp = mp->next;
- }
-
- return min_mp;
-}
-
-static void
-assign_minipool_offsets (Mfix *barrier)
-{
- HOST_WIDE_INT offset = 0;
- Mnode *mp;
-
- minipool_barrier = barrier;
-
- for (mp = minipool_vector_head; mp != NULL; mp = mp->next)
- {
- mp->offset = offset;
-
- if (mp->refcount > 0)
- offset += mp->fix_size;
- }
-}
-
-/* Output the literal table */
-static void
-dump_minipool (rtx scan)
-{
- Mnode * mp;
- Mnode * nmp;
- int align64 = 0;
-
- if (ARM_DOUBLEWORD_ALIGN)
- for (mp = minipool_vector_head; mp != NULL; mp = mp->next)
- if (mp->refcount > 0 && mp->fix_size == 8)
- {
- align64 = 1;
- break;
- }
-
- if (dump_file)
- fprintf (dump_file,
- ";; Emitting minipool after insn %u; address %ld; align %d (bytes)\n",
- INSN_UID (scan), (unsigned long) minipool_barrier->address, align64 ? 8 : 4);
-
- scan = emit_label_after (gen_label_rtx (), scan);
- scan = emit_insn_after (align64 ? gen_align_8 () : gen_align_4 (), scan);
- scan = emit_label_after (minipool_vector_label, scan);
-
- for (mp = minipool_vector_head; mp != NULL; mp = nmp)
- {
- if (mp->refcount > 0)
- {
- if (dump_file)
- {
- fprintf (dump_file,
- ";; Offset %u, min %ld, max %ld ",
- (unsigned) mp->offset, (unsigned long) mp->min_address,
- (unsigned long) mp->max_address);
- arm_print_value (dump_file, mp->value);
- fputc ('\n', dump_file);
- }
-
- switch (mp->fix_size)
- {
-#ifdef HAVE_consttable_1
- case 1:
- scan = emit_insn_after (gen_consttable_1 (mp->value), scan);
- break;
-
-#endif
-#ifdef HAVE_consttable_2
- case 2:
- scan = emit_insn_after (gen_consttable_2 (mp->value), scan);
- break;
-
-#endif
-#ifdef HAVE_consttable_4
- case 4:
- scan = emit_insn_after (gen_consttable_4 (mp->value), scan);
- break;
-
-#endif
-#ifdef HAVE_consttable_8
- case 8:
- scan = emit_insn_after (gen_consttable_8 (mp->value), scan);
- break;
-
-#endif
- default:
- gcc_unreachable ();
- }
- }
-
- nmp = mp->next;
- free (mp);
- }
-
- minipool_vector_head = minipool_vector_tail = NULL;
- scan = emit_insn_after (gen_consttable_end (), scan);
- scan = emit_barrier_after (scan);
-}
-
-/* Return the cost of forcibly inserting a barrier after INSN. */
-static int
-arm_barrier_cost (rtx insn)
-{
- /* Basing the location of the pool on the loop depth is preferable,
- but at the moment, the basic block information seems to be
- corrupt by this stage of the compilation. */
- int base_cost = 50;
- rtx next = next_nonnote_insn (insn);
-
- if (next != NULL && GET_CODE (next) == CODE_LABEL)
- base_cost -= 20;
-
- switch (GET_CODE (insn))
- {
- case CODE_LABEL:
- /* It will always be better to place the table before the label, rather
- than after it. */
- return 50;
-
- case INSN:
- case CALL_INSN:
- return base_cost;
-
- case JUMP_INSN:
- return base_cost - 10;
-
- default:
- return base_cost + 10;
- }
-}
-
-/* Find the best place in the insn stream in the range
- (FIX->address,MAX_ADDRESS) to forcibly insert a minipool barrier.
- Create the barrier by inserting a jump and add a new fix entry for
- it. */
-static Mfix *
-create_fix_barrier (Mfix *fix, HOST_WIDE_INT max_address)
-{
- HOST_WIDE_INT count = 0;
- rtx barrier;
- rtx from = fix->insn;
- /* The instruction after which we will insert the jump. */
- rtx selected = NULL;
- int selected_cost;
- /* The address at which the jump instruction will be placed. */
- HOST_WIDE_INT selected_address;
- Mfix * new_fix;
- HOST_WIDE_INT max_count = max_address - fix->address;
- rtx label = gen_label_rtx ();
-
- selected_cost = arm_barrier_cost (from);
- selected_address = fix->address;
-
- while (from && count < max_count)
- {
- rtx tmp;
- int new_cost;
-
- /* This code shouldn't have been called if there was a natural barrier
- within range. */
- gcc_assert (GET_CODE (from) != BARRIER);
-
- /* Count the length of this insn. */
- count += get_attr_length (from);
-
- /* If there is a jump table, add its length. */
- tmp = is_jump_table (from);
- if (tmp != NULL)
- {
- count += get_jump_table_size (tmp);
-
- /* Jump tables aren't in a basic block, so base the cost on
- the dispatch insn. If we select this location, we will
- still put the pool after the table. */
- new_cost = arm_barrier_cost (from);
-
- if (count < max_count
- && (!selected || new_cost <= selected_cost))
- {
- selected = tmp;
- selected_cost = new_cost;
- selected_address = fix->address + count;
- }
-
- /* Continue after the dispatch table. */
- from = NEXT_INSN (tmp);
- continue;
- }
-
- new_cost = arm_barrier_cost (from);
-
- if (count < max_count
- && (!selected || new_cost <= selected_cost))
- {
- selected = from;
- selected_cost = new_cost;
- selected_address = fix->address + count;
- }
-
- from = NEXT_INSN (from);
- }
-
- /* Make sure that we found a place to insert the jump. */
- gcc_assert (selected);
-
- /* Create a new JUMP_INSN that branches around a barrier. */
- from = emit_jump_insn_after (gen_jump (label), selected);
- JUMP_LABEL (from) = label;
- barrier = emit_barrier_after (from);
- emit_label_after (label, barrier);
-
- /* Create a minipool barrier entry for the new barrier. */
- new_fix = (Mfix *) obstack_alloc (&minipool_obstack, sizeof (* new_fix));
- new_fix->insn = barrier;
- new_fix->address = selected_address;
- new_fix->next = fix->next;
- fix->next = new_fix;
-
- return new_fix;
-}
-
-/* Record that there is a natural barrier in the insn stream at
- ADDRESS. */
-static void
-push_minipool_barrier (rtx insn, HOST_WIDE_INT address)
-{
- Mfix * fix = (Mfix *) obstack_alloc (&minipool_obstack, sizeof (* fix));
-
- fix->insn = insn;
- fix->address = address;
-
- fix->next = NULL;
- if (minipool_fix_head != NULL)
- minipool_fix_tail->next = fix;
- else
- minipool_fix_head = fix;
-
- minipool_fix_tail = fix;
-}
-
-/* Record INSN, which will need fixing up to load a value from the
- minipool. ADDRESS is the offset of the insn since the start of the
- function; LOC is a pointer to the part of the insn which requires
- fixing; VALUE is the constant that must be loaded, which is of type
- MODE. */
-static void
-push_minipool_fix (rtx insn, HOST_WIDE_INT address, rtx *loc,
- enum machine_mode mode, rtx value)
-{
- Mfix * fix = (Mfix *) obstack_alloc (&minipool_obstack, sizeof (* fix));
-
-#ifdef AOF_ASSEMBLER
- /* PIC symbol references need to be converted into offsets into the
- based area. */
- /* XXX This shouldn't be done here. */
- if (flag_pic && GET_CODE (value) == SYMBOL_REF)
- value = aof_pic_entry (value);
-#endif /* AOF_ASSEMBLER */
-
- fix->insn = insn;
- fix->address = address;
- fix->loc = loc;
- fix->mode = mode;
- fix->fix_size = MINIPOOL_FIX_SIZE (mode);
- fix->value = value;
- fix->forwards = get_attr_pool_range (insn);
- fix->backwards = get_attr_neg_pool_range (insn);
- fix->minipool = NULL;
-
- /* If an insn doesn't have a range defined for it, then it isn't
- expecting to be reworked by this code. Better to stop now than
- to generate duff assembly code. */
- gcc_assert (fix->forwards || fix->backwards);
-
- /* If an entry requires 8-byte alignment then assume all constant pools
- require 4 bytes of padding. Trying to do this later on a per-pool
- basis is awkward because existing pool entries have to be modified. */
- if (ARM_DOUBLEWORD_ALIGN && fix->fix_size == 8)
- minipool_pad = 4;
-
- if (dump_file)
- {
- fprintf (dump_file,
- ";; %smode fixup for i%d; addr %lu, range (%ld,%ld): ",
- GET_MODE_NAME (mode),
- INSN_UID (insn), (unsigned long) address,
- -1 * (long)fix->backwards, (long)fix->forwards);
- arm_print_value (dump_file, fix->value);
- fprintf (dump_file, "\n");
- }
-
- /* Add it to the chain of fixes. */
- fix->next = NULL;
-
- if (minipool_fix_head != NULL)
- minipool_fix_tail->next = fix;
- else
- minipool_fix_head = fix;
-
- minipool_fix_tail = fix;
-}
-
-/* Return the cost of synthesizing a 64-bit constant VAL inline.
- Returns the number of insns needed, or 99 if we don't know how to
- do it. */
-int
-arm_const_double_inline_cost (rtx val)
-{
- rtx lowpart, highpart;
- enum machine_mode mode;
-
- mode = GET_MODE (val);
-
- if (mode == VOIDmode)
- mode = DImode;
-
- gcc_assert (GET_MODE_SIZE (mode) == 8);
-
- lowpart = gen_lowpart (SImode, val);
- highpart = gen_highpart_mode (SImode, mode, val);
-
- gcc_assert (GET_CODE (lowpart) == CONST_INT);
- gcc_assert (GET_CODE (highpart) == CONST_INT);
-
- return (arm_gen_constant (SET, SImode, NULL_RTX, INTVAL (lowpart),
- NULL_RTX, NULL_RTX, 0, 0)
- + arm_gen_constant (SET, SImode, NULL_RTX, INTVAL (highpart),
- NULL_RTX, NULL_RTX, 0, 0));
-}
-
-/* Return true if it is worthwhile to split a 64-bit constant into two
- 32-bit operations. This is the case if optimizing for size, or
- if we have load delay slots, or if one 32-bit part can be done with
- a single data operation. */
-bool
-arm_const_double_by_parts (rtx val)
-{
- enum machine_mode mode = GET_MODE (val);
- rtx part;
-
- if (optimize_size || arm_ld_sched)
- return true;
-
- if (mode == VOIDmode)
- mode = DImode;
-
- part = gen_highpart_mode (SImode, mode, val);
-
- gcc_assert (GET_CODE (part) == CONST_INT);
-
- if (const_ok_for_arm (INTVAL (part))
- || const_ok_for_arm (~INTVAL (part)))
- return true;
-
- part = gen_lowpart (SImode, val);
-
- gcc_assert (GET_CODE (part) == CONST_INT);
-
- if (const_ok_for_arm (INTVAL (part))
- || const_ok_for_arm (~INTVAL (part)))
- return true;
-
- return false;
-}
-
-/* Scan INSN and note any of its operands that need fixing.
- If DO_PUSHES is false we do not actually push any of the fixups
- needed. The function returns TRUE if any fixups were needed/pushed.
- This is used by arm_memory_load_p() which needs to know about loads
- of constants that will be converted into minipool loads. */
-static bool
-note_invalid_constants (rtx insn, HOST_WIDE_INT address, int do_pushes)
-{
- bool result = false;
- int opno;
-
- extract_insn (insn);
-
- if (!constrain_operands (1))
- fatal_insn_not_found (insn);
-
- if (recog_data.n_alternatives == 0)
- return false;
-
- /* Fill in recog_op_alt with information about the constraints of
- this insn. */
- preprocess_constraints ();
-
- for (opno = 0; opno < recog_data.n_operands; opno++)
- {
- /* Things we need to fix can only occur in inputs. */
- if (recog_data.operand_type[opno] != OP_IN)
- continue;
-
- /* If this alternative is a memory reference, then any mention
- of constants in this alternative is really to fool reload
- into allowing us to accept one there. We need to fix them up
- now so that we output the right code. */
- if (recog_op_alt[opno][which_alternative].memory_ok)
- {
- rtx op = recog_data.operand[opno];
-
- if (CONSTANT_P (op))
- {
- if (do_pushes)
- push_minipool_fix (insn, address, recog_data.operand_loc[opno],
- recog_data.operand_mode[opno], op);
- result = true;
- }
- else if (GET_CODE (op) == MEM
- && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (XEXP (op, 0)))
- {
- if (do_pushes)
- {
- rtx cop = avoid_constant_pool_reference (op);
-
- /* Casting the address of something to a mode narrower
- than a word can cause avoid_constant_pool_reference()
- to return the pool reference itself. That's no good to
- us here. Lets just hope that we can use the
- constant pool value directly. */
- if (op == cop)
- cop = get_pool_constant (XEXP (op, 0));
-
- push_minipool_fix (insn, address,
- recog_data.operand_loc[opno],
- recog_data.operand_mode[opno], cop);
- }
-
- result = true;
- }
- }
- }
-
- return result;
-}
-
-/* Gcc puts the pool in the wrong place for ARM, since we can only
- load addresses a limited distance around the pc. We do some
- special munging to move the constant pool values to the correct
- point in the code. */
-static void
-arm_reorg (void)
-{
- rtx insn;
- HOST_WIDE_INT address = 0;
- Mfix * fix;
-
- minipool_fix_head = minipool_fix_tail = NULL;
-
- /* The first insn must always be a note, or the code below won't
- scan it properly. */
- insn = get_insns ();
- gcc_assert (GET_CODE (insn) == NOTE);
- minipool_pad = 0;
-
- /* Scan all the insns and record the operands that will need fixing. */
- for (insn = next_nonnote_insn (insn); insn; insn = next_nonnote_insn (insn))
- {
- if (TARGET_CIRRUS_FIX_INVALID_INSNS
- && (arm_cirrus_insn_p (insn)
- || GET_CODE (insn) == JUMP_INSN
- || arm_memory_load_p (insn)))
- cirrus_reorg (insn);
-
- if (GET_CODE (insn) == BARRIER)
- push_minipool_barrier (insn, address);
- else if (INSN_P (insn))
- {
- rtx table;
-
- note_invalid_constants (insn, address, true);
- address += get_attr_length (insn);
-
- /* If the insn is a vector jump, add the size of the table
- and skip the table. */
- if ((table = is_jump_table (insn)) != NULL)
- {
- address += get_jump_table_size (table);
- insn = table;
- }
- }
- }
-
- fix = minipool_fix_head;
-
- /* Now scan the fixups and perform the required changes. */
- while (fix)
- {
- Mfix * ftmp;
- Mfix * fdel;
- Mfix * last_added_fix;
- Mfix * last_barrier = NULL;
- Mfix * this_fix;
-
- /* Skip any further barriers before the next fix. */
- while (fix && GET_CODE (fix->insn) == BARRIER)
- fix = fix->next;
-
- /* No more fixes. */
- if (fix == NULL)
- break;
-
- last_added_fix = NULL;
-
- for (ftmp = fix; ftmp; ftmp = ftmp->next)
- {
- if (GET_CODE (ftmp->insn) == BARRIER)
- {
- if (ftmp->address >= minipool_vector_head->max_address)
- break;
-
- last_barrier = ftmp;
- }
- else if ((ftmp->minipool = add_minipool_forward_ref (ftmp)) == NULL)
- break;
-
- last_added_fix = ftmp; /* Keep track of the last fix added. */
- }
-
- /* If we found a barrier, drop back to that; any fixes that we
- could have reached but come after the barrier will now go in
- the next mini-pool. */
- if (last_barrier != NULL)
- {
- /* Reduce the refcount for those fixes that won't go into this
- pool after all. */
- for (fdel = last_barrier->next;
- fdel && fdel != ftmp;
- fdel = fdel->next)
- {
- fdel->minipool->refcount--;
- fdel->minipool = NULL;
- }
-
- ftmp = last_barrier;
- }
- else
- {
- /* ftmp is first fix that we can't fit into this pool and
- there no natural barriers that we could use. Insert a
- new barrier in the code somewhere between the previous
- fix and this one, and arrange to jump around it. */
- HOST_WIDE_INT max_address;
-
- /* The last item on the list of fixes must be a barrier, so
- we can never run off the end of the list of fixes without
- last_barrier being set. */
- gcc_assert (ftmp);
-
- max_address = minipool_vector_head->max_address;
- /* Check that there isn't another fix that is in range that
- we couldn't fit into this pool because the pool was
- already too large: we need to put the pool before such an
- instruction. The pool itself may come just after the
- fix because create_fix_barrier also allows space for a
- jump instruction. */
- if (ftmp->address < max_address)
- max_address = ftmp->address + 1;
-
- last_barrier = create_fix_barrier (last_added_fix, max_address);
- }
-
- assign_minipool_offsets (last_barrier);
-
- while (ftmp)
- {
- if (GET_CODE (ftmp->insn) != BARRIER
- && ((ftmp->minipool = add_minipool_backward_ref (ftmp))
- == NULL))
- break;
-
- ftmp = ftmp->next;
- }
-
- /* Scan over the fixes we have identified for this pool, fixing them
- up and adding the constants to the pool itself. */
- for (this_fix = fix; this_fix && ftmp != this_fix;
- this_fix = this_fix->next)
- if (GET_CODE (this_fix->insn) != BARRIER)
- {
- rtx addr
- = plus_constant (gen_rtx_LABEL_REF (VOIDmode,
- minipool_vector_label),
- this_fix->minipool->offset);
- *this_fix->loc = gen_rtx_MEM (this_fix->mode, addr);
- }
-
- dump_minipool (last_barrier->insn);
- fix = ftmp;
- }
-
- /* From now on we must synthesize any constants that we can't handle
- directly. This can happen if the RTL gets split during final
- instruction generation. */
- after_arm_reorg = 1;
-
- /* Free the minipool memory. */
- obstack_free (&minipool_obstack, minipool_startobj);
-}
-
-/* Routines to output assembly language. */
-
-/* If the rtx is the correct value then return the string of the number.
- In this way we can ensure that valid double constants are generated even
- when cross compiling. */
-const char *
-fp_immediate_constant (rtx x)
-{
- REAL_VALUE_TYPE r;
- int i;
-
- if (!fp_consts_inited)
- init_fp_table ();
-
- REAL_VALUE_FROM_CONST_DOUBLE (r, x);
- for (i = 0; i < 8; i++)
- if (REAL_VALUES_EQUAL (r, values_fp[i]))
- return strings_fp[i];
-
- gcc_unreachable ();
-}
-
-/* As for fp_immediate_constant, but value is passed directly, not in rtx. */
-static const char *
-fp_const_from_val (REAL_VALUE_TYPE *r)
-{
- int i;
-
- if (!fp_consts_inited)
- init_fp_table ();
-
- for (i = 0; i < 8; i++)
- if (REAL_VALUES_EQUAL (*r, values_fp[i]))
- return strings_fp[i];
-
- gcc_unreachable ();
-}
-
-/* Output the operands of a LDM/STM instruction to STREAM.
- MASK is the ARM register set mask of which only bits 0-15 are important.
- REG is the base register, either the frame pointer or the stack pointer,
- INSTR is the possibly suffixed load or store instruction. */
-
-static void
-print_multi_reg (FILE *stream, const char *instr, unsigned reg,
- unsigned long mask)
-{
- unsigned i;
- bool not_first = FALSE;
-
- fputc ('\t', stream);
- asm_fprintf (stream, instr, reg);
- fputs (", {", stream);
-
- for (i = 0; i <= LAST_ARM_REGNUM; i++)
- if (mask & (1 << i))
- {
- if (not_first)
- fprintf (stream, ", ");
-
- asm_fprintf (stream, "%r", i);
- not_first = TRUE;
- }
-
- fprintf (stream, "}\n");
-}
-
-
-/* Output a FLDMX instruction to STREAM.
- BASE if the register containing the address.
- REG and COUNT specify the register range.
- Extra registers may be added to avoid hardware bugs. */
-
-static void
-arm_output_fldmx (FILE * stream, unsigned int base, int reg, int count)
-{
- int i;
-
- /* Workaround ARM10 VFPr1 bug. */
- if (count == 2 && !arm_arch6)
- {
- if (reg == 15)
- reg--;
- count++;
- }
-
- fputc ('\t', stream);
- asm_fprintf (stream, "fldmfdx\t%r!, {", base);
-
- for (i = reg; i < reg + count; i++)
- {
- if (i > reg)
- fputs (", ", stream);
- asm_fprintf (stream, "d%d", i);
- }
- fputs ("}\n", stream);
-
-}
-
-
-/* Output the assembly for a store multiple. */
-
-const char *
-vfp_output_fstmx (rtx * operands)
-{
- char pattern[100];
- int p;
- int base;
- int i;
-
- strcpy (pattern, "fstmfdx\t%m0!, {%P1");
- p = strlen (pattern);
-
- gcc_assert (GET_CODE (operands[1]) == REG);
-
- base = (REGNO (operands[1]) - FIRST_VFP_REGNUM) / 2;
- for (i = 1; i < XVECLEN (operands[2], 0); i++)
- {
- p += sprintf (&pattern[p], ", d%d", base + i);
- }
- strcpy (&pattern[p], "}");
-
- output_asm_insn (pattern, operands);
- return "";
-}
-
-
-/* Emit RTL to save block of VFP register pairs to the stack. Returns the
- number of bytes pushed. */
-
-static int
-vfp_emit_fstmx (int base_reg, int count)
-{
- rtx par;
- rtx dwarf;
- rtx tmp, reg;
- int i;
-
- /* Workaround ARM10 VFPr1 bug. Data corruption can occur when exactly two
- register pairs are stored by a store multiple insn. We avoid this
- by pushing an extra pair. */
- if (count == 2 && !arm_arch6)
- {
- if (base_reg == LAST_VFP_REGNUM - 3)
- base_reg -= 2;
- count++;
- }
-
- /* ??? The frame layout is implementation defined. We describe
- standard format 1 (equivalent to a FSTMD insn and unused pad word).
- We really need some way of representing the whole block so that the
- unwinder can figure it out at runtime. */
- par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
- dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (count + 1));
-
- reg = gen_rtx_REG (DFmode, base_reg);
- base_reg += 2;
-
- XVECEXP (par, 0, 0)
- = gen_rtx_SET (VOIDmode,
- gen_frame_mem (BLKmode,
- gen_rtx_PRE_DEC (BLKmode,
- stack_pointer_rtx)),
- gen_rtx_UNSPEC (BLKmode,
- gen_rtvec (1, reg),
- UNSPEC_PUSH_MULT));
-
- tmp = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
- plus_constant (stack_pointer_rtx, -(count * 8 + 4)));
- RTX_FRAME_RELATED_P (tmp) = 1;
- XVECEXP (dwarf, 0, 0) = tmp;
-
- tmp = gen_rtx_SET (VOIDmode,
- gen_frame_mem (DFmode, stack_pointer_rtx),
- reg);
- RTX_FRAME_RELATED_P (tmp) = 1;
- XVECEXP (dwarf, 0, 1) = tmp;
-
- for (i = 1; i < count; i++)
- {
- reg = gen_rtx_REG (DFmode, base_reg);
- base_reg += 2;
- XVECEXP (par, 0, i) = gen_rtx_USE (VOIDmode, reg);
-
- tmp = gen_rtx_SET (VOIDmode,
- gen_frame_mem (DFmode,
- plus_constant (stack_pointer_rtx,
- i * 8)),
- reg);
- RTX_FRAME_RELATED_P (tmp) = 1;
- XVECEXP (dwarf, 0, i + 1) = tmp;
- }
-
- par = emit_insn (par);
- REG_NOTES (par) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
- REG_NOTES (par));
- RTX_FRAME_RELATED_P (par) = 1;
-
- return count * 8 + 4;
-}
-
-
-/* Output a 'call' insn. */
-const char *
-output_call (rtx *operands)
-{
- gcc_assert (!arm_arch5); /* Patterns should call blx <reg> directly. */
-
- /* Handle calls to lr using ip (which may be clobbered in subr anyway). */
- if (REGNO (operands[0]) == LR_REGNUM)
- {
- operands[0] = gen_rtx_REG (SImode, IP_REGNUM);
- output_asm_insn ("mov%?\t%0, %|lr", operands);
- }
-
- output_asm_insn ("mov%?\t%|lr, %|pc", operands);
-
- if (TARGET_INTERWORK || arm_arch4t)
- output_asm_insn ("bx%?\t%0", operands);
- else
- output_asm_insn ("mov%?\t%|pc, %0", operands);
-
- return "";
-}
-
-/* Output a 'call' insn that is a reference in memory. */
-const char *
-output_call_mem (rtx *operands)
-{
- if (TARGET_INTERWORK && !arm_arch5)
- {
- output_asm_insn ("ldr%?\t%|ip, %0", operands);
- output_asm_insn ("mov%?\t%|lr, %|pc", operands);
- output_asm_insn ("bx%?\t%|ip", operands);
- }
- else if (regno_use_in (LR_REGNUM, operands[0]))
- {
- /* LR is used in the memory address. We load the address in the
- first instruction. It's safe to use IP as the target of the
- load since the call will kill it anyway. */
- output_asm_insn ("ldr%?\t%|ip, %0", operands);
- if (arm_arch5)
- output_asm_insn ("blx%?\t%|ip", operands);
- else
- {
- output_asm_insn ("mov%?\t%|lr, %|pc", operands);
- if (arm_arch4t)
- output_asm_insn ("bx%?\t%|ip", operands);
- else
- output_asm_insn ("mov%?\t%|pc, %|ip", operands);
- }
- }
- else
- {
- output_asm_insn ("mov%?\t%|lr, %|pc", operands);
- output_asm_insn ("ldr%?\t%|pc, %0", operands);
- }
-
- return "";
-}
-
-
-/* Output a move from arm registers to an fpa registers.
- OPERANDS[0] is an fpa register.
- OPERANDS[1] is the first registers of an arm register pair. */
-const char *
-output_mov_long_double_fpa_from_arm (rtx *operands)
-{
- int arm_reg0 = REGNO (operands[1]);
- rtx ops[3];
-
- gcc_assert (arm_reg0 != IP_REGNUM);
-
- ops[0] = gen_rtx_REG (SImode, arm_reg0);
- ops[1] = gen_rtx_REG (SImode, 1 + arm_reg0);
- ops[2] = gen_rtx_REG (SImode, 2 + arm_reg0);
-
- output_asm_insn ("stm%?fd\t%|sp!, {%0, %1, %2}", ops);
- output_asm_insn ("ldf%?e\t%0, [%|sp], #12", operands);
-
- return "";
-}
-
-/* Output a move from an fpa register to arm registers.
- OPERANDS[0] is the first registers of an arm register pair.
- OPERANDS[1] is an fpa register. */
-const char *
-output_mov_long_double_arm_from_fpa (rtx *operands)
-{
- int arm_reg0 = REGNO (operands[0]);
- rtx ops[3];
-
- gcc_assert (arm_reg0 != IP_REGNUM);
-
- ops[0] = gen_rtx_REG (SImode, arm_reg0);
- ops[1] = gen_rtx_REG (SImode, 1 + arm_reg0);
- ops[2] = gen_rtx_REG (SImode, 2 + arm_reg0);
-
- output_asm_insn ("stf%?e\t%1, [%|sp, #-12]!", operands);
- output_asm_insn ("ldm%?fd\t%|sp!, {%0, %1, %2}", ops);
- return "";
-}
-
-/* Output a move from arm registers to arm registers of a long double
- OPERANDS[0] is the destination.
- OPERANDS[1] is the source. */
-const char *
-output_mov_long_double_arm_from_arm (rtx *operands)
-{
- /* We have to be careful here because the two might overlap. */
- int dest_start = REGNO (operands[0]);
- int src_start = REGNO (operands[1]);
- rtx ops[2];
- int i;
-
- if (dest_start < src_start)
- {
- for (i = 0; i < 3; i++)
- {
- ops[0] = gen_rtx_REG (SImode, dest_start + i);
- ops[1] = gen_rtx_REG (SImode, src_start + i);
- output_asm_insn ("mov%?\t%0, %1", ops);
- }
- }
- else
- {
- for (i = 2; i >= 0; i--)
- {
- ops[0] = gen_rtx_REG (SImode, dest_start + i);
- ops[1] = gen_rtx_REG (SImode, src_start + i);
- output_asm_insn ("mov%?\t%0, %1", ops);
- }
- }
-
- return "";
-}
-
-
-/* Output a move from arm registers to an fpa registers.
- OPERANDS[0] is an fpa register.
- OPERANDS[1] is the first registers of an arm register pair. */
-const char *
-output_mov_double_fpa_from_arm (rtx *operands)
-{
- int arm_reg0 = REGNO (operands[1]);
- rtx ops[2];
-
- gcc_assert (arm_reg0 != IP_REGNUM);
-
- ops[0] = gen_rtx_REG (SImode, arm_reg0);
- ops[1] = gen_rtx_REG (SImode, 1 + arm_reg0);
- output_asm_insn ("stm%?fd\t%|sp!, {%0, %1}", ops);
- output_asm_insn ("ldf%?d\t%0, [%|sp], #8", operands);
- return "";
-}
-
-/* Output a move from an fpa register to arm registers.
- OPERANDS[0] is the first registers of an arm register pair.
- OPERANDS[1] is an fpa register. */
-const char *
-output_mov_double_arm_from_fpa (rtx *operands)
-{
- int arm_reg0 = REGNO (operands[0]);
- rtx ops[2];
-
- gcc_assert (arm_reg0 != IP_REGNUM);
-
- ops[0] = gen_rtx_REG (SImode, arm_reg0);
- ops[1] = gen_rtx_REG (SImode, 1 + arm_reg0);
- output_asm_insn ("stf%?d\t%1, [%|sp, #-8]!", operands);
- output_asm_insn ("ldm%?fd\t%|sp!, {%0, %1}", ops);
- return "";
-}
-
-/* Output a move between double words.
- It must be REG<-REG, REG<-CONST_DOUBLE, REG<-CONST_INT, REG<-MEM
- or MEM<-REG and all MEMs must be offsettable addresses. */
-const char *
-output_move_double (rtx *operands)
-{
- enum rtx_code code0 = GET_CODE (operands[0]);
- enum rtx_code code1 = GET_CODE (operands[1]);
- rtx otherops[3];
-
- if (code0 == REG)
- {
- int reg0 = REGNO (operands[0]);
-
- otherops[0] = gen_rtx_REG (SImode, 1 + reg0);
-
- gcc_assert (code1 == MEM); /* Constraints should ensure this. */
-
- switch (GET_CODE (XEXP (operands[1], 0)))
- {
- case REG:
- output_asm_insn ("ldm%?ia\t%m1, %M0", operands);
- break;
-
- case PRE_INC:
- gcc_assert (TARGET_LDRD);
- output_asm_insn ("ldr%?d\t%0, [%m1, #8]!", operands);
- break;
-
- case PRE_DEC:
- output_asm_insn ("ldm%?db\t%m1!, %M0", operands);
- break;
-
- case POST_INC:
- output_asm_insn ("ldm%?ia\t%m1!, %M0", operands);
- break;
-
- case POST_DEC:
- gcc_assert (TARGET_LDRD);
- output_asm_insn ("ldr%?d\t%0, [%m1], #-8", operands);
- break;
-
- case PRE_MODIFY:
- case POST_MODIFY:
- otherops[0] = operands[0];
- otherops[1] = XEXP (XEXP (XEXP (operands[1], 0), 1), 0);
- otherops[2] = XEXP (XEXP (XEXP (operands[1], 0), 1), 1);
-
- if (GET_CODE (XEXP (operands[1], 0)) == PRE_MODIFY)
- {
- if (reg_overlap_mentioned_p (otherops[0], otherops[2]))
- {
- /* Registers overlap so split out the increment. */
- output_asm_insn ("add%?\t%1, %1, %2", otherops);
- output_asm_insn ("ldr%?d\t%0, [%1] @split", otherops);
- }
- else
- {
- /* IWMMXT allows offsets larger than ldrd can handle,
- fix these up with a pair of ldr. */
- if (GET_CODE (otherops[2]) == CONST_INT
- && (INTVAL(otherops[2]) <= -256
- || INTVAL(otherops[2]) >= 256))
- {
- output_asm_insn ("ldr%?\t%0, [%1, %2]!", otherops);
- otherops[0] = gen_rtx_REG (SImode, 1 + reg0);
- output_asm_insn ("ldr%?\t%0, [%1, #4]", otherops);
- }
- else
- output_asm_insn ("ldr%?d\t%0, [%1, %2]!", otherops);
- }
- }
- else
- {
- /* IWMMXT allows offsets larger than ldrd can handle,
- fix these up with a pair of ldr. */
- if (GET_CODE (otherops[2]) == CONST_INT
- && (INTVAL(otherops[2]) <= -256
- || INTVAL(otherops[2]) >= 256))
- {
- otherops[0] = gen_rtx_REG (SImode, 1 + reg0);
- output_asm_insn ("ldr%?\t%0, [%1, #4]", otherops);
- otherops[0] = operands[0];
- output_asm_insn ("ldr%?\t%0, [%1], %2", otherops);
- }
- else
- /* We only allow constant increments, so this is safe. */
- output_asm_insn ("ldr%?d\t%0, [%1], %2", otherops);
- }
- break;
-
- case LABEL_REF:
- case CONST:
- output_asm_insn ("adr%?\t%0, %1", operands);
- output_asm_insn ("ldm%?ia\t%0, %M0", operands);
- break;
-
- default:
- if (arm_add_operand (XEXP (XEXP (operands[1], 0), 1),
- GET_MODE (XEXP (XEXP (operands[1], 0), 1))))
- {
- otherops[0] = operands[0];
- otherops[1] = XEXP (XEXP (operands[1], 0), 0);
- otherops[2] = XEXP (XEXP (operands[1], 0), 1);
-
- if (GET_CODE (XEXP (operands[1], 0)) == PLUS)
- {
- if (GET_CODE (otherops[2]) == CONST_INT)
- {
- switch ((int) INTVAL (otherops[2]))
- {
- case -8:
- output_asm_insn ("ldm%?db\t%1, %M0", otherops);
- return "";
- case -4:
- output_asm_insn ("ldm%?da\t%1, %M0", otherops);
- return "";
- case 4:
- output_asm_insn ("ldm%?ib\t%1, %M0", otherops);
- return "";
- }
- }
- if (TARGET_LDRD
- && (GET_CODE (otherops[2]) == REG
- || (GET_CODE (otherops[2]) == CONST_INT
- && INTVAL (otherops[2]) > -256
- && INTVAL (otherops[2]) < 256)))
- {
- if (reg_overlap_mentioned_p (otherops[0],
- otherops[2]))
- {
- /* Swap base and index registers over to
- avoid a conflict. */
- otherops[1] = XEXP (XEXP (operands[1], 0), 1);
- otherops[2] = XEXP (XEXP (operands[1], 0), 0);
- }
- /* If both registers conflict, it will usually
- have been fixed by a splitter. */
- if (reg_overlap_mentioned_p (otherops[0], otherops[2]))
- {
- output_asm_insn ("add%?\t%1, %1, %2", otherops);
- output_asm_insn ("ldr%?d\t%0, [%1]",
- otherops);
- }
- else
- output_asm_insn ("ldr%?d\t%0, [%1, %2]", otherops);
- return "";
- }
-
- if (GET_CODE (otherops[2]) == CONST_INT)
- {
- if (!(const_ok_for_arm (INTVAL (otherops[2]))))
- output_asm_insn ("sub%?\t%0, %1, #%n2", otherops);
- else
- output_asm_insn ("add%?\t%0, %1, %2", otherops);
- }
- else
- output_asm_insn ("add%?\t%0, %1, %2", otherops);
- }
- else
- output_asm_insn ("sub%?\t%0, %1, %2", otherops);
-
- return "ldm%?ia\t%0, %M0";
- }
- else
- {
- otherops[1] = adjust_address (operands[1], SImode, 4);
- /* Take care of overlapping base/data reg. */
- if (reg_mentioned_p (operands[0], operands[1]))
- {
- output_asm_insn ("ldr%?\t%0, %1", otherops);
- output_asm_insn ("ldr%?\t%0, %1", operands);
- }
- else
- {
- output_asm_insn ("ldr%?\t%0, %1", operands);
- output_asm_insn ("ldr%?\t%0, %1", otherops);
- }
- }
- }
- }
- else
- {
- /* Constraints should ensure this. */
- gcc_assert (code0 == MEM && code1 == REG);
- gcc_assert (REGNO (operands[1]) != IP_REGNUM);
-
- switch (GET_CODE (XEXP (operands[0], 0)))
- {
- case REG:
- output_asm_insn ("stm%?ia\t%m0, %M1", operands);
- break;
-
- case PRE_INC:
- gcc_assert (TARGET_LDRD);
- output_asm_insn ("str%?d\t%1, [%m0, #8]!", operands);
- break;
-
- case PRE_DEC:
- output_asm_insn ("stm%?db\t%m0!, %M1", operands);
- break;
-
- case POST_INC:
- output_asm_insn ("stm%?ia\t%m0!, %M1", operands);
- break;
-
- case POST_DEC:
- gcc_assert (TARGET_LDRD);
- output_asm_insn ("str%?d\t%1, [%m0], #-8", operands);
- break;
-
- case PRE_MODIFY:
- case POST_MODIFY:
- otherops[0] = operands[1];
- otherops[1] = XEXP (XEXP (XEXP (operands[0], 0), 1), 0);
- otherops[2] = XEXP (XEXP (XEXP (operands[0], 0), 1), 1);
-
- /* IWMMXT allows offsets larger than ldrd can handle,
- fix these up with a pair of ldr. */
- if (GET_CODE (otherops[2]) == CONST_INT
- && (INTVAL(otherops[2]) <= -256
- || INTVAL(otherops[2]) >= 256))
- {
- rtx reg1;
- reg1 = gen_rtx_REG (SImode, 1 + REGNO (operands[1]));
- if (GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY)
- {
- output_asm_insn ("ldr%?\t%0, [%1, %2]!", otherops);
- otherops[0] = reg1;
- output_asm_insn ("ldr%?\t%0, [%1, #4]", otherops);
- }
- else
- {
- otherops[0] = reg1;
- output_asm_insn ("ldr%?\t%0, [%1, #4]", otherops);
- otherops[0] = operands[1];
- output_asm_insn ("ldr%?\t%0, [%1], %2", otherops);
- }
- }
- else if (GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY)
- output_asm_insn ("str%?d\t%0, [%1, %2]!", otherops);
- else
- output_asm_insn ("str%?d\t%0, [%1], %2", otherops);
- break;
-
- case PLUS:
- otherops[2] = XEXP (XEXP (operands[0], 0), 1);
- if (GET_CODE (otherops[2]) == CONST_INT)
- {
- switch ((int) INTVAL (XEXP (XEXP (operands[0], 0), 1)))
- {
- case -8:
- output_asm_insn ("stm%?db\t%m0, %M1", operands);
- return "";
-
- case -4:
- output_asm_insn ("stm%?da\t%m0, %M1", operands);
- return "";
-
- case 4:
- output_asm_insn ("stm%?ib\t%m0, %M1", operands);
- return "";
- }
- }
- if (TARGET_LDRD
- && (GET_CODE (otherops[2]) == REG
- || (GET_CODE (otherops[2]) == CONST_INT
- && INTVAL (otherops[2]) > -256
- && INTVAL (otherops[2]) < 256)))
- {
- otherops[0] = operands[1];
- otherops[1] = XEXP (XEXP (operands[0], 0), 0);
- output_asm_insn ("str%?d\t%0, [%1, %2]", otherops);
- return "";
- }
- /* Fall through */
-
- default:
- otherops[0] = adjust_address (operands[0], SImode, 4);
- otherops[1] = gen_rtx_REG (SImode, 1 + REGNO (operands[1]));
- output_asm_insn ("str%?\t%1, %0", operands);
- output_asm_insn ("str%?\t%1, %0", otherops);
- }
- }
-
- return "";
-}
-
-/* Output an ADD r, s, #n where n may be too big for one instruction.
- If adding zero to one register, output nothing. */
-const char *
-output_add_immediate (rtx *operands)
-{
- HOST_WIDE_INT n = INTVAL (operands[2]);
-
- if (n != 0 || REGNO (operands[0]) != REGNO (operands[1]))
- {
- if (n < 0)
- output_multi_immediate (operands,
- "sub%?\t%0, %1, %2", "sub%?\t%0, %0, %2", 2,
- -n);
- else
- output_multi_immediate (operands,
- "add%?\t%0, %1, %2", "add%?\t%0, %0, %2", 2,
- n);
- }
-
- return "";
-}
-
-/* Output a multiple immediate operation.
- OPERANDS is the vector of operands referred to in the output patterns.
- INSTR1 is the output pattern to use for the first constant.
- INSTR2 is the output pattern to use for subsequent constants.
- IMMED_OP is the index of the constant slot in OPERANDS.
- N is the constant value. */
-static const char *
-output_multi_immediate (rtx *operands, const char *instr1, const char *instr2,
- int immed_op, HOST_WIDE_INT n)
-{
-#if HOST_BITS_PER_WIDE_INT > 32
- n &= 0xffffffff;
-#endif
-
- if (n == 0)
- {
- /* Quick and easy output. */
- operands[immed_op] = const0_rtx;
- output_asm_insn (instr1, operands);
- }
- else
- {
- int i;
- const char * instr = instr1;
-
- /* Note that n is never zero here (which would give no output). */
- for (i = 0; i < 32; i += 2)
- {
- if (n & (3 << i))
- {
- operands[immed_op] = GEN_INT (n & (255 << i));
- output_asm_insn (instr, operands);
- instr = instr2;
- i += 6;
- }
- }
- }
-
- return "";
-}
-
-/* Return the appropriate ARM instruction for the operation code.
- The returned result should not be overwritten. OP is the rtx of the
- operation. SHIFT_FIRST_ARG is TRUE if the first argument of the operator
- was shifted. */
-const char *
-arithmetic_instr (rtx op, int shift_first_arg)
-{
- switch (GET_CODE (op))
- {
- case PLUS:
- return "add";
-
- case MINUS:
- return shift_first_arg ? "rsb" : "sub";
-
- case IOR:
- return "orr";
-
- case XOR:
- return "eor";
-
- case AND:
- return "and";
-
- default:
- gcc_unreachable ();
- }
-}
-
-/* Ensure valid constant shifts and return the appropriate shift mnemonic
- for the operation code. The returned result should not be overwritten.
- OP is the rtx code of the shift.
- On exit, *AMOUNTP will be -1 if the shift is by a register, or a constant
- shift. */
-static const char *
-shift_op (rtx op, HOST_WIDE_INT *amountp)
-{
- const char * mnem;
- enum rtx_code code = GET_CODE (op);
-
- switch (GET_CODE (XEXP (op, 1)))
- {
- case REG:
- case SUBREG:
- *amountp = -1;
- break;
-
- case CONST_INT:
- *amountp = INTVAL (XEXP (op, 1));
- break;
-
- default:
- gcc_unreachable ();
- }
-
- switch (code)
- {
- case ASHIFT:
- mnem = "asl";
- break;
-
- case ASHIFTRT:
- mnem = "asr";
- break;
-
- case LSHIFTRT:
- mnem = "lsr";
- break;
-
- case ROTATE:
- gcc_assert (*amountp != -1);
- *amountp = 32 - *amountp;
-
- /* Fall through. */
-
- case ROTATERT:
- mnem = "ror";
- break;
-
- case MULT:
- /* We never have to worry about the amount being other than a
- power of 2, since this case can never be reloaded from a reg. */
- gcc_assert (*amountp != -1);
- *amountp = int_log2 (*amountp);
- return "asl";
-
- default:
- gcc_unreachable ();
- }
-
- if (*amountp != -1)
- {
- /* This is not 100% correct, but follows from the desire to merge
- multiplication by a power of 2 with the recognizer for a
- shift. >=32 is not a valid shift for "asl", so we must try and
- output a shift that produces the correct arithmetical result.
- Using lsr #32 is identical except for the fact that the carry bit
- is not set correctly if we set the flags; but we never use the
- carry bit from such an operation, so we can ignore that. */
- if (code == ROTATERT)
- /* Rotate is just modulo 32. */
- *amountp &= 31;
- else if (*amountp != (*amountp & 31))
- {
- if (code == ASHIFT)
- mnem = "lsr";
- *amountp = 32;
- }
-
- /* Shifts of 0 are no-ops. */
- if (*amountp == 0)
- return NULL;
- }
-
- return mnem;
-}
-
-/* Obtain the shift from the POWER of two. */
-
-static HOST_WIDE_INT
-int_log2 (HOST_WIDE_INT power)
-{
- HOST_WIDE_INT shift = 0;
-
- while ((((HOST_WIDE_INT) 1 << shift) & power) == 0)
- {
- gcc_assert (shift <= 31);
- shift++;
- }
-
- return shift;
-}
-
-/* Output a .ascii pseudo-op, keeping track of lengths. This is
- because /bin/as is horribly restrictive. The judgement about
- whether or not each character is 'printable' (and can be output as
- is) or not (and must be printed with an octal escape) must be made
- with reference to the *host* character set -- the situation is
- similar to that discussed in the comments above pp_c_char in
- c-pretty-print.c. */
-
-#define MAX_ASCII_LEN 51
-
-void
-output_ascii_pseudo_op (FILE *stream, const unsigned char *p, int len)
-{
- int i;
- int len_so_far = 0;
-
- fputs ("\t.ascii\t\"", stream);
-
- for (i = 0; i < len; i++)
- {
- int c = p[i];
-
- if (len_so_far >= MAX_ASCII_LEN)
- {
- fputs ("\"\n\t.ascii\t\"", stream);
- len_so_far = 0;
- }
-
- if (ISPRINT (c))
- {
- if (c == '\\' || c == '\"')
- {
- putc ('\\', stream);
- len_so_far++;
- }
- putc (c, stream);
- len_so_far++;
- }
- else
- {
- fprintf (stream, "\\%03o", c);
- len_so_far += 4;
- }
- }
-
- fputs ("\"\n", stream);
-}
-
-/* Compute the register save mask for registers 0 through 12
- inclusive. This code is used by arm_compute_save_reg_mask. */
-
-static unsigned long
-arm_compute_save_reg0_reg12_mask (void)
-{
- unsigned long func_type = arm_current_func_type ();
- unsigned long save_reg_mask = 0;
- unsigned int reg;
-
- if (IS_INTERRUPT (func_type))
- {
- unsigned int max_reg;
- /* Interrupt functions must not corrupt any registers,
- even call clobbered ones. If this is a leaf function
- we can just examine the registers used by the RTL, but
- otherwise we have to assume that whatever function is
- called might clobber anything, and so we have to save
- all the call-clobbered registers as well. */
- if (ARM_FUNC_TYPE (func_type) == ARM_FT_FIQ)
- /* FIQ handlers have registers r8 - r12 banked, so
- we only need to check r0 - r7, Normal ISRs only
- bank r14 and r15, so we must check up to r12.
- r13 is the stack pointer which is always preserved,
- so we do not need to consider it here. */
- max_reg = 7;
- else
- max_reg = 12;
-
- for (reg = 0; reg <= max_reg; reg++)
- if (regs_ever_live[reg]
- || (! current_function_is_leaf && call_used_regs [reg]))
- save_reg_mask |= (1 << reg);
-
- /* Also save the pic base register if necessary. */
- if (flag_pic
- && !TARGET_SINGLE_PIC_BASE
- && arm_pic_register != INVALID_REGNUM
- && current_function_uses_pic_offset_table)
- save_reg_mask |= 1 << PIC_OFFSET_TABLE_REGNUM;
- }
- else
- {
- /* In the normal case we only need to save those registers
- which are call saved and which are used by this function. */
- for (reg = 0; reg <= 10; reg++)
- if (regs_ever_live[reg] && ! call_used_regs [reg])
- save_reg_mask |= (1 << reg);
-
- /* Handle the frame pointer as a special case. */
- if (! TARGET_APCS_FRAME
- && ! frame_pointer_needed
- && regs_ever_live[HARD_FRAME_POINTER_REGNUM]
- && ! call_used_regs[HARD_FRAME_POINTER_REGNUM])
- save_reg_mask |= 1 << HARD_FRAME_POINTER_REGNUM;
-
- /* If we aren't loading the PIC register,
- don't stack it even though it may be live. */
- if (flag_pic
- && !TARGET_SINGLE_PIC_BASE
- && arm_pic_register != INVALID_REGNUM
- && (regs_ever_live[PIC_OFFSET_TABLE_REGNUM]
- || current_function_uses_pic_offset_table))
- save_reg_mask |= 1 << PIC_OFFSET_TABLE_REGNUM;
- }
-
- /* Save registers so the exception handler can modify them. */
- if (current_function_calls_eh_return)
- {
- unsigned int i;
-
- for (i = 0; ; i++)
- {
- reg = EH_RETURN_DATA_REGNO (i);
- if (reg == INVALID_REGNUM)
- break;
- save_reg_mask |= 1 << reg;
- }
- }
-
- return save_reg_mask;
-}
-
-/* Compute a bit mask of which registers need to be
- saved on the stack for the current function. */
-
-static unsigned long
-arm_compute_save_reg_mask (void)
-{
- unsigned int save_reg_mask = 0;
- unsigned long func_type = arm_current_func_type ();
-
- if (IS_NAKED (func_type))
- /* This should never really happen. */
- return 0;
-
- /* If we are creating a stack frame, then we must save the frame pointer,
- IP (which will hold the old stack pointer), LR and the PC. */
- if (frame_pointer_needed)
- save_reg_mask |=
- (1 << ARM_HARD_FRAME_POINTER_REGNUM)
- | (1 << IP_REGNUM)
- | (1 << LR_REGNUM)
- | (1 << PC_REGNUM);
-
- /* Volatile functions do not return, so there
- is no need to save any other registers. */
- if (IS_VOLATILE (func_type))
- return save_reg_mask;
-
- save_reg_mask |= arm_compute_save_reg0_reg12_mask ();
-
- /* Decide if we need to save the link register.
- Interrupt routines have their own banked link register,
- so they never need to save it.
- Otherwise if we do not use the link register we do not need to save
- it. If we are pushing other registers onto the stack however, we
- can save an instruction in the epilogue by pushing the link register
- now and then popping it back into the PC. This incurs extra memory
- accesses though, so we only do it when optimizing for size, and only
- if we know that we will not need a fancy return sequence. */
- if (regs_ever_live [LR_REGNUM]
- || (save_reg_mask
- && optimize_size
- && ARM_FUNC_TYPE (func_type) == ARM_FT_NORMAL
- && !current_function_calls_eh_return))
- save_reg_mask |= 1 << LR_REGNUM;
-
- if (cfun->machine->lr_save_eliminated)
- save_reg_mask &= ~ (1 << LR_REGNUM);
-
- if (TARGET_REALLY_IWMMXT
- && ((bit_count (save_reg_mask)
- + ARM_NUM_INTS (current_function_pretend_args_size)) % 2) != 0)
- {
- unsigned int reg;
-
- /* The total number of registers that are going to be pushed
- onto the stack is odd. We need to ensure that the stack
- is 64-bit aligned before we start to save iWMMXt registers,
- and also before we start to create locals. (A local variable
- might be a double or long long which we will load/store using
- an iWMMXt instruction). Therefore we need to push another
- ARM register, so that the stack will be 64-bit aligned. We
- try to avoid using the arg registers (r0 -r3) as they might be
- used to pass values in a tail call. */
- for (reg = 4; reg <= 12; reg++)
- if ((save_reg_mask & (1 << reg)) == 0)
- break;
-
- if (reg <= 12)
- save_reg_mask |= (1 << reg);
- else
- {
- cfun->machine->sibcall_blocked = 1;
- save_reg_mask |= (1 << 3);
- }
- }
-
- return save_reg_mask;
-}
-
-
-/* Compute a bit mask of which registers need to be
- saved on the stack for the current function. */
-static unsigned long
-thumb_compute_save_reg_mask (void)
-{
- unsigned long mask;
- unsigned reg;
-
- mask = 0;
- for (reg = 0; reg < 12; reg ++)
- if (regs_ever_live[reg] && !call_used_regs[reg])
- mask |= 1 << reg;
-
- if (flag_pic
- && !TARGET_SINGLE_PIC_BASE
- && arm_pic_register != INVALID_REGNUM
- && current_function_uses_pic_offset_table)
- mask |= 1 << PIC_OFFSET_TABLE_REGNUM;
-
- /* See if we might need r11 for calls to _interwork_r11_call_via_rN(). */
- if (!frame_pointer_needed && CALLER_INTERWORKING_SLOT_SIZE > 0)
- mask |= 1 << ARM_HARD_FRAME_POINTER_REGNUM;
-
- /* LR will also be pushed if any lo regs are pushed. */
- if (mask & 0xff || thumb_force_lr_save ())
- mask |= (1 << LR_REGNUM);
-
- /* Make sure we have a low work register if we need one.
- We will need one if we are going to push a high register,
- but we are not currently intending to push a low register. */
- if ((mask & 0xff) == 0
- && ((mask & 0x0f00) || TARGET_BACKTRACE))
- {
- /* Use thumb_find_work_register to choose which register
- we will use. If the register is live then we will
- have to push it. Use LAST_LO_REGNUM as our fallback
- choice for the register to select. */
- reg = thumb_find_work_register (1 << LAST_LO_REGNUM);
-
- if (! call_used_regs[reg])
- mask |= 1 << reg;
- }
-
- return mask;
-}
-
-
-/* Return the number of bytes required to save VFP registers. */
-static int
-arm_get_vfp_saved_size (void)
-{
- unsigned int regno;
- int count;
- int saved;
-
- saved = 0;
- /* Space for saved VFP registers. */
- if (TARGET_HARD_FLOAT && TARGET_VFP)
- {
- count = 0;
- for (regno = FIRST_VFP_REGNUM;
- regno < LAST_VFP_REGNUM;
- regno += 2)
- {
- if ((!regs_ever_live[regno] || call_used_regs[regno])
- && (!regs_ever_live[regno + 1] || call_used_regs[regno + 1]))
- {
- if (count > 0)
- {
- /* Workaround ARM10 VFPr1 bug. */
- if (count == 2 && !arm_arch6)
- count++;
- saved += count * 8 + 4;
- }
- count = 0;
- }
- else
- count++;
- }
- if (count > 0)
- {
- if (count == 2 && !arm_arch6)
- count++;
- saved += count * 8 + 4;
- }
- }
- return saved;
-}
-
-
-/* Generate a function exit sequence. If REALLY_RETURN is false, then do
- everything bar the final return instruction. */
-const char *
-output_return_instruction (rtx operand, int really_return, int reverse)
-{
- char conditional[10];
- char instr[100];
- unsigned reg;
- unsigned long live_regs_mask;
- unsigned long func_type;
- arm_stack_offsets *offsets;
-
- func_type = arm_current_func_type ();
-
- if (IS_NAKED (func_type))
- return "";
-
- if (IS_VOLATILE (func_type) && TARGET_ABORT_NORETURN)
- {
- /* If this function was declared non-returning, and we have
- found a tail call, then we have to trust that the called
- function won't return. */
- if (really_return)
- {
- rtx ops[2];
-
- /* Otherwise, trap an attempted return by aborting. */
- ops[0] = operand;
- ops[1] = gen_rtx_SYMBOL_REF (Pmode, NEED_PLT_RELOC ? "abort(PLT)"
- : "abort");
- assemble_external_libcall (ops[1]);
- output_asm_insn (reverse ? "bl%D0\t%a1" : "bl%d0\t%a1", ops);
- }
-
- return "";
- }
-
- gcc_assert (!current_function_calls_alloca || really_return);
-
- sprintf (conditional, "%%?%%%c0", reverse ? 'D' : 'd');
-
- return_used_this_function = 1;
-
- live_regs_mask = arm_compute_save_reg_mask ();
-
- if (live_regs_mask)
- {
- const char * return_reg;
-
- /* If we do not have any special requirements for function exit
- (e.g. interworking, or ISR) then we can load the return address
- directly into the PC. Otherwise we must load it into LR. */
- if (really_return
- && ! TARGET_INTERWORK)
- return_reg = reg_names[PC_REGNUM];
- else
- return_reg = reg_names[LR_REGNUM];
-
- if ((live_regs_mask & (1 << IP_REGNUM)) == (1 << IP_REGNUM))
- {
- /* There are three possible reasons for the IP register
- being saved. 1) a stack frame was created, in which case
- IP contains the old stack pointer, or 2) an ISR routine
- corrupted it, or 3) it was saved to align the stack on
- iWMMXt. In case 1, restore IP into SP, otherwise just
- restore IP. */
- if (frame_pointer_needed)
- {
- live_regs_mask &= ~ (1 << IP_REGNUM);
- live_regs_mask |= (1 << SP_REGNUM);
- }
- else
- gcc_assert (IS_INTERRUPT (func_type) || TARGET_REALLY_IWMMXT);
- }
-
- /* On some ARM architectures it is faster to use LDR rather than
- LDM to load a single register. On other architectures, the
- cost is the same. In 26 bit mode, or for exception handlers,
- we have to use LDM to load the PC so that the CPSR is also
- restored. */
- for (reg = 0; reg <= LAST_ARM_REGNUM; reg++)
- if (live_regs_mask == (1U << reg))
- break;
-
- if (reg <= LAST_ARM_REGNUM
- && (reg != LR_REGNUM
- || ! really_return
- || ! IS_INTERRUPT (func_type)))
- {
- sprintf (instr, "ldr%s\t%%|%s, [%%|sp], #4", conditional,
- (reg == LR_REGNUM) ? return_reg : reg_names[reg]);
- }
- else
- {
- char *p;
- int first = 1;
-
- /* Generate the load multiple instruction to restore the
- registers. Note we can get here, even if
- frame_pointer_needed is true, but only if sp already
- points to the base of the saved core registers. */
- if (live_regs_mask & (1 << SP_REGNUM))
- {
- unsigned HOST_WIDE_INT stack_adjust;
-
- offsets = arm_get_frame_offsets ();
- stack_adjust = offsets->outgoing_args - offsets->saved_regs;
- gcc_assert (stack_adjust == 0 || stack_adjust == 4);
-
- if (stack_adjust && arm_arch5)
- sprintf (instr, "ldm%sib\t%%|sp, {", conditional);
- else
- {
- /* If we can't use ldmib (SA110 bug),
- then try to pop r3 instead. */
- if (stack_adjust)
- live_regs_mask |= 1 << 3;
- sprintf (instr, "ldm%sfd\t%%|sp, {", conditional);
- }
- }
- else
- sprintf (instr, "ldm%sfd\t%%|sp!, {", conditional);
-
- p = instr + strlen (instr);
-
- for (reg = 0; reg <= SP_REGNUM; reg++)
- if (live_regs_mask & (1 << reg))
- {
- int l = strlen (reg_names[reg]);
-
- if (first)
- first = 0;
- else
- {
- memcpy (p, ", ", 2);
- p += 2;
- }
-
- memcpy (p, "%|", 2);
- memcpy (p + 2, reg_names[reg], l);
- p += l + 2;
- }
-
- if (live_regs_mask & (1 << LR_REGNUM))
- {
- sprintf (p, "%s%%|%s}", first ? "" : ", ", return_reg);
- /* If returning from an interrupt, restore the CPSR. */
- if (IS_INTERRUPT (func_type))
- strcat (p, "^");
- }
- else
- strcpy (p, "}");
- }
-
- output_asm_insn (instr, & operand);
-
- /* See if we need to generate an extra instruction to
- perform the actual function return. */
- if (really_return
- && func_type != ARM_FT_INTERWORKED
- && (live_regs_mask & (1 << LR_REGNUM)) != 0)
- {
- /* The return has already been handled
- by loading the LR into the PC. */
- really_return = 0;
- }
- }
-
- if (really_return)
- {
- switch ((int) ARM_FUNC_TYPE (func_type))
- {
- case ARM_FT_ISR:
- case ARM_FT_FIQ:
- sprintf (instr, "sub%ss\t%%|pc, %%|lr, #4", conditional);
- break;
-
- case ARM_FT_INTERWORKED:
- sprintf (instr, "bx%s\t%%|lr", conditional);
- break;
-
- case ARM_FT_EXCEPTION:
- sprintf (instr, "mov%ss\t%%|pc, %%|lr", conditional);
- break;
-
- default:
- /* Use bx if it's available. */
- if (arm_arch5 || arm_arch4t)
- sprintf (instr, "bx%s\t%%|lr", conditional);
- else
- sprintf (instr, "mov%s\t%%|pc, %%|lr", conditional);
- break;
- }
-
- output_asm_insn (instr, & operand);
- }
-
- return "";
-}
-
-/* Write the function name into the code section, directly preceding
- the function prologue.
-
- Code will be output similar to this:
- t0
- .ascii "arm_poke_function_name", 0
- .align
- t1
- .word 0xff000000 + (t1 - t0)
- arm_poke_function_name
- mov ip, sp
- stmfd sp!, {fp, ip, lr, pc}
- sub fp, ip, #4
-
- When performing a stack backtrace, code can inspect the value
- of 'pc' stored at 'fp' + 0. If the trace function then looks
- at location pc - 12 and the top 8 bits are set, then we know
- that there is a function name embedded immediately preceding this
- location and has length ((pc[-3]) & 0xff000000).
-
- We assume that pc is declared as a pointer to an unsigned long.
-
- It is of no benefit to output the function name if we are assembling
- a leaf function. These function types will not contain a stack
- backtrace structure, therefore it is not possible to determine the
- function name. */
-void
-arm_poke_function_name (FILE *stream, const char *name)
-{
- unsigned long alignlength;
- unsigned long length;
- rtx x;
-
- length = strlen (name) + 1;
- alignlength = ROUND_UP_WORD (length);
-
- ASM_OUTPUT_ASCII (stream, name, length);
- ASM_OUTPUT_ALIGN (stream, 2);
- x = GEN_INT ((unsigned HOST_WIDE_INT) 0xff000000 + alignlength);
- assemble_aligned_integer (UNITS_PER_WORD, x);
-}
-
-/* Place some comments into the assembler stream
- describing the current function. */
-static void
-arm_output_function_prologue (FILE *f, HOST_WIDE_INT frame_size)
-{
- unsigned long func_type;
-
- if (!TARGET_ARM)
- {
- thumb_output_function_prologue (f, frame_size);
- return;
- }
-
- /* Sanity check. */
- gcc_assert (!arm_ccfsm_state && !arm_target_insn);
-
- func_type = arm_current_func_type ();
-
- switch ((int) ARM_FUNC_TYPE (func_type))
- {
- default:
- case ARM_FT_NORMAL:
- break;
- case ARM_FT_INTERWORKED:
- asm_fprintf (f, "\t%@ Function supports interworking.\n");
- break;
- case ARM_FT_ISR:
- asm_fprintf (f, "\t%@ Interrupt Service Routine.\n");
- break;
- case ARM_FT_FIQ:
- asm_fprintf (f, "\t%@ Fast Interrupt Service Routine.\n");
- break;
- case ARM_FT_EXCEPTION:
- asm_fprintf (f, "\t%@ ARM Exception Handler.\n");
- break;
- }
-
- if (IS_NAKED (func_type))
- asm_fprintf (f, "\t%@ Naked Function: prologue and epilogue provided by programmer.\n");
-
- if (IS_VOLATILE (func_type))
- asm_fprintf (f, "\t%@ Volatile: function does not return.\n");
-
- if (IS_NESTED (func_type))
- asm_fprintf (f, "\t%@ Nested: function declared inside another function.\n");
-
- asm_fprintf (f, "\t%@ args = %d, pretend = %d, frame = %wd\n",
- current_function_args_size,
- current_function_pretend_args_size, frame_size);
-
- asm_fprintf (f, "\t%@ frame_needed = %d, uses_anonymous_args = %d\n",
- frame_pointer_needed,
- cfun->machine->uses_anonymous_args);
-
- if (cfun->machine->lr_save_eliminated)
- asm_fprintf (f, "\t%@ link register save eliminated.\n");
-
- if (current_function_calls_eh_return)
- asm_fprintf (f, "\t@ Calls __builtin_eh_return.\n");
-
-#ifdef AOF_ASSEMBLER
- if (flag_pic)
- asm_fprintf (f, "\tmov\t%r, %r\n", IP_REGNUM, PIC_OFFSET_TABLE_REGNUM);
-#endif
-
- return_used_this_function = 0;
-}
-
-const char *
-arm_output_epilogue (rtx sibling)
-{
- int reg;
- unsigned long saved_regs_mask;
- unsigned long func_type;
- /* Floats_offset is the offset from the "virtual" frame. In an APCS
- frame that is $fp + 4 for a non-variadic function. */
- int floats_offset = 0;
- rtx operands[3];
- FILE * f = asm_out_file;
- unsigned int lrm_count = 0;
- int really_return = (sibling == NULL);
- int start_reg;
- arm_stack_offsets *offsets;
-
- /* If we have already generated the return instruction
- then it is futile to generate anything else. */
- if (use_return_insn (FALSE, sibling) && return_used_this_function)
- return "";
-
- func_type = arm_current_func_type ();
-
- if (IS_NAKED (func_type))
- /* Naked functions don't have epilogues. */
- return "";
-
- if (IS_VOLATILE (func_type) && TARGET_ABORT_NORETURN)
- {
- rtx op;
-
- /* A volatile function should never return. Call abort. */
- op = gen_rtx_SYMBOL_REF (Pmode, NEED_PLT_RELOC ? "abort(PLT)" : "abort");
- assemble_external_libcall (op);
- output_asm_insn ("bl\t%a0", &op);
-
- return "";
- }
-
- /* If we are throwing an exception, then we really must be doing a
- return, so we can't tail-call. */
- gcc_assert (!current_function_calls_eh_return || really_return);
-
- offsets = arm_get_frame_offsets ();
- saved_regs_mask = arm_compute_save_reg_mask ();
-
- if (TARGET_IWMMXT)
- lrm_count = bit_count (saved_regs_mask);
-
- floats_offset = offsets->saved_args;
- /* Compute how far away the floats will be. */
- for (reg = 0; reg <= LAST_ARM_REGNUM; reg++)
- if (saved_regs_mask & (1 << reg))
- floats_offset += 4;
-
- if (frame_pointer_needed)
- {
- /* This variable is for the Virtual Frame Pointer, not VFP regs. */
- int vfp_offset = offsets->frame;
-
- if (arm_fpu_arch == FPUTYPE_FPA_EMU2)
- {
- for (reg = LAST_FPA_REGNUM; reg >= FIRST_FPA_REGNUM; reg--)
- if (regs_ever_live[reg] && !call_used_regs[reg])
- {
- floats_offset += 12;
- asm_fprintf (f, "\tldfe\t%r, [%r, #-%d]\n",
- reg, FP_REGNUM, floats_offset - vfp_offset);
- }
- }
- else
- {
- start_reg = LAST_FPA_REGNUM;
-
- for (reg = LAST_FPA_REGNUM; reg >= FIRST_FPA_REGNUM; reg--)
- {
- if (regs_ever_live[reg] && !call_used_regs[reg])
- {
- floats_offset += 12;
-
- /* We can't unstack more than four registers at once. */
- if (start_reg - reg == 3)
- {
- asm_fprintf (f, "\tlfm\t%r, 4, [%r, #-%d]\n",
- reg, FP_REGNUM, floats_offset - vfp_offset);
- start_reg = reg - 1;
- }
- }
- else
- {
- if (reg != start_reg)
- asm_fprintf (f, "\tlfm\t%r, %d, [%r, #-%d]\n",
- reg + 1, start_reg - reg,
- FP_REGNUM, floats_offset - vfp_offset);
- start_reg = reg - 1;
- }
- }
-
- /* Just in case the last register checked also needs unstacking. */
- if (reg != start_reg)
- asm_fprintf (f, "\tlfm\t%r, %d, [%r, #-%d]\n",
- reg + 1, start_reg - reg,
- FP_REGNUM, floats_offset - vfp_offset);
- }
-
- if (TARGET_HARD_FLOAT && TARGET_VFP)
- {
- int saved_size;
-
- /* The fldmx insn does not have base+offset addressing modes,
- so we use IP to hold the address. */
- saved_size = arm_get_vfp_saved_size ();
-
- if (saved_size > 0)
- {
- floats_offset += saved_size;
- asm_fprintf (f, "\tsub\t%r, %r, #%d\n", IP_REGNUM,
- FP_REGNUM, floats_offset - vfp_offset);
- }
- start_reg = FIRST_VFP_REGNUM;
- for (reg = FIRST_VFP_REGNUM; reg < LAST_VFP_REGNUM; reg += 2)
- {
- if ((!regs_ever_live[reg] || call_used_regs[reg])
- && (!regs_ever_live[reg + 1] || call_used_regs[reg + 1]))
- {
- if (start_reg != reg)
- arm_output_fldmx (f, IP_REGNUM,
- (start_reg - FIRST_VFP_REGNUM) / 2,
- (reg - start_reg) / 2);
- start_reg = reg + 2;
- }
- }
- if (start_reg != reg)
- arm_output_fldmx (f, IP_REGNUM,
- (start_reg - FIRST_VFP_REGNUM) / 2,
- (reg - start_reg) / 2);
- }
-
- if (TARGET_IWMMXT)
- {
- /* The frame pointer is guaranteed to be non-double-word aligned.
- This is because it is set to (old_stack_pointer - 4) and the
- old_stack_pointer was double word aligned. Thus the offset to
- the iWMMXt registers to be loaded must also be non-double-word
- sized, so that the resultant address *is* double-word aligned.
- We can ignore floats_offset since that was already included in
- the live_regs_mask. */
- lrm_count += (lrm_count % 2 ? 2 : 1);
-
- for (reg = LAST_IWMMXT_REGNUM; reg >= FIRST_IWMMXT_REGNUM; reg--)
- if (regs_ever_live[reg] && !call_used_regs[reg])
- {
- asm_fprintf (f, "\twldrd\t%r, [%r, #-%d]\n",
- reg, FP_REGNUM, lrm_count * 4);
- lrm_count += 2;
- }
- }
-
- /* saved_regs_mask should contain the IP, which at the time of stack
- frame generation actually contains the old stack pointer. So a
- quick way to unwind the stack is just pop the IP register directly
- into the stack pointer. */
- gcc_assert (saved_regs_mask & (1 << IP_REGNUM));
- saved_regs_mask &= ~ (1 << IP_REGNUM);
- saved_regs_mask |= (1 << SP_REGNUM);
-
- /* There are two registers left in saved_regs_mask - LR and PC. We
- only need to restore the LR register (the return address), but to
- save time we can load it directly into the PC, unless we need a
- special function exit sequence, or we are not really returning. */
- if (really_return
- && ARM_FUNC_TYPE (func_type) == ARM_FT_NORMAL
- && !current_function_calls_eh_return)
- /* Delete the LR from the register mask, so that the LR on
- the stack is loaded into the PC in the register mask. */
- saved_regs_mask &= ~ (1 << LR_REGNUM);
- else
- saved_regs_mask &= ~ (1 << PC_REGNUM);
-
- /* We must use SP as the base register, because SP is one of the
- registers being restored. If an interrupt or page fault
- happens in the ldm instruction, the SP might or might not
- have been restored. That would be bad, as then SP will no
- longer indicate the safe area of stack, and we can get stack
- corruption. Using SP as the base register means that it will
- be reset correctly to the original value, should an interrupt
- occur. If the stack pointer already points at the right
- place, then omit the subtraction. */
- if (offsets->outgoing_args != (1 + (int) bit_count (saved_regs_mask))
- || current_function_calls_alloca)
- asm_fprintf (f, "\tsub\t%r, %r, #%d\n", SP_REGNUM, FP_REGNUM,
- 4 * bit_count (saved_regs_mask));
- print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask);
-
- if (IS_INTERRUPT (func_type))
- /* Interrupt handlers will have pushed the
- IP onto the stack, so restore it now. */
- print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, 1 << IP_REGNUM);
- }
- else
- {
- /* Restore stack pointer if necessary. */
- if (offsets->outgoing_args != offsets->saved_regs)
- {
- operands[0] = operands[1] = stack_pointer_rtx;
- operands[2] = GEN_INT (offsets->outgoing_args - offsets->saved_regs);
- output_add_immediate (operands);
- }
-
- if (arm_fpu_arch == FPUTYPE_FPA_EMU2)
- {
- for (reg = FIRST_FPA_REGNUM; reg <= LAST_FPA_REGNUM; reg++)
- if (regs_ever_live[reg] && !call_used_regs[reg])
- asm_fprintf (f, "\tldfe\t%r, [%r], #12\n",
- reg, SP_REGNUM);
- }
- else
- {
- start_reg = FIRST_FPA_REGNUM;
-
- for (reg = FIRST_FPA_REGNUM; reg <= LAST_FPA_REGNUM; reg++)
- {
- if (regs_ever_live[reg] && !call_used_regs[reg])
- {
- if (reg - start_reg == 3)
- {
- asm_fprintf (f, "\tlfmfd\t%r, 4, [%r]!\n",
- start_reg, SP_REGNUM);
- start_reg = reg + 1;
- }
- }
- else
- {
- if (reg != start_reg)
- asm_fprintf (f, "\tlfmfd\t%r, %d, [%r]!\n",
- start_reg, reg - start_reg,
- SP_REGNUM);
-
- start_reg = reg + 1;
- }
- }
-
- /* Just in case the last register checked also needs unstacking. */
- if (reg != start_reg)
- asm_fprintf (f, "\tlfmfd\t%r, %d, [%r]!\n",
- start_reg, reg - start_reg, SP_REGNUM);
- }
-
- if (TARGET_HARD_FLOAT && TARGET_VFP)
- {
- start_reg = FIRST_VFP_REGNUM;
- for (reg = FIRST_VFP_REGNUM; reg < LAST_VFP_REGNUM; reg += 2)
- {
- if ((!regs_ever_live[reg] || call_used_regs[reg])
- && (!regs_ever_live[reg + 1] || call_used_regs[reg + 1]))
- {
- if (start_reg != reg)
- arm_output_fldmx (f, SP_REGNUM,
- (start_reg - FIRST_VFP_REGNUM) / 2,
- (reg - start_reg) / 2);
- start_reg = reg + 2;
- }
- }
- if (start_reg != reg)
- arm_output_fldmx (f, SP_REGNUM,
- (start_reg - FIRST_VFP_REGNUM) / 2,
- (reg - start_reg) / 2);
- }
- if (TARGET_IWMMXT)
- for (reg = FIRST_IWMMXT_REGNUM; reg <= LAST_IWMMXT_REGNUM; reg++)
- if (regs_ever_live[reg] && !call_used_regs[reg])
- asm_fprintf (f, "\twldrd\t%r, [%r], #8\n", reg, SP_REGNUM);
-
- /* If we can, restore the LR into the PC. */
- if (ARM_FUNC_TYPE (func_type) == ARM_FT_NORMAL
- && really_return
- && current_function_pretend_args_size == 0
- && saved_regs_mask & (1 << LR_REGNUM)
- && !current_function_calls_eh_return)
- {
- saved_regs_mask &= ~ (1 << LR_REGNUM);
- saved_regs_mask |= (1 << PC_REGNUM);
- }
-
- /* Load the registers off the stack. If we only have one register
- to load use the LDR instruction - it is faster. */
- if (saved_regs_mask == (1 << LR_REGNUM))
- {
- asm_fprintf (f, "\tldr\t%r, [%r], #4\n", LR_REGNUM, SP_REGNUM);
- }
- else if (saved_regs_mask)
- {
- if (saved_regs_mask & (1 << SP_REGNUM))
- /* Note - write back to the stack register is not enabled
- (i.e. "ldmfd sp!..."). We know that the stack pointer is
- in the list of registers and if we add writeback the
- instruction becomes UNPREDICTABLE. */
- print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask);
- else
- print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, saved_regs_mask);
- }
-
- if (current_function_pretend_args_size)
- {
- /* Unwind the pre-pushed regs. */
- operands[0] = operands[1] = stack_pointer_rtx;
- operands[2] = GEN_INT (current_function_pretend_args_size);
- output_add_immediate (operands);
- }
- }
-
- /* We may have already restored PC directly from the stack. */
- if (!really_return || saved_regs_mask & (1 << PC_REGNUM))
- return "";
-
- /* Stack adjustment for exception handler. */
- if (current_function_calls_eh_return)
- asm_fprintf (f, "\tadd\t%r, %r, %r\n", SP_REGNUM, SP_REGNUM,
- ARM_EH_STACKADJ_REGNUM);
-
- /* Generate the return instruction. */
- switch ((int) ARM_FUNC_TYPE (func_type))
- {
- case ARM_FT_ISR:
- case ARM_FT_FIQ:
- asm_fprintf (f, "\tsubs\t%r, %r, #4\n", PC_REGNUM, LR_REGNUM);
- break;
-
- case ARM_FT_EXCEPTION:
- asm_fprintf (f, "\tmovs\t%r, %r\n", PC_REGNUM, LR_REGNUM);
- break;
-
- case ARM_FT_INTERWORKED:
- asm_fprintf (f, "\tbx\t%r\n", LR_REGNUM);
- break;
-
- default:
- if (arm_arch5 || arm_arch4t)
- asm_fprintf (f, "\tbx\t%r\n", LR_REGNUM);
- else
- asm_fprintf (f, "\tmov\t%r, %r\n", PC_REGNUM, LR_REGNUM);
- break;
- }
-
- return "";
-}
-
-static void
-arm_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
- HOST_WIDE_INT frame_size ATTRIBUTE_UNUSED)
-{
- arm_stack_offsets *offsets;
-
- if (TARGET_THUMB)
- {
- int regno;
-
- /* Emit any call-via-reg trampolines that are needed for v4t support
- of call_reg and call_value_reg type insns. */
- for (regno = 0; regno < LR_REGNUM; regno++)
- {
- rtx label = cfun->machine->call_via[regno];
-
- if (label != NULL)
- {
- switch_to_section (function_section (current_function_decl));
- targetm.asm_out.internal_label (asm_out_file, "L",
- CODE_LABEL_NUMBER (label));
- asm_fprintf (asm_out_file, "\tbx\t%r\n", regno);
- }
- }
-
- /* ??? 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;
- }
- else
- {
- /* We need to take into account any stack-frame rounding. */
- offsets = arm_get_frame_offsets ();
-
- gcc_assert (!use_return_insn (FALSE, NULL)
- || !return_used_this_function
- || offsets->saved_regs == offsets->outgoing_args
- || frame_pointer_needed);
-
- /* Reset the ARM-specific per-function variables. */
- after_arm_reorg = 0;
- }
-}
-
-/* Generate and emit an insn that we will recognize as a push_multi.
- Unfortunately, since this insn does not reflect very well the actual
- semantics of the operation, we need to annotate the insn for the benefit
- of DWARF2 frame unwind information. */
-static rtx
-emit_multi_reg_push (unsigned long mask)
-{
- int num_regs = 0;
- int num_dwarf_regs;
- int i, j;
- rtx par;
- rtx dwarf;
- int dwarf_par_index;
- rtx tmp, reg;
-
- for (i = 0; i <= LAST_ARM_REGNUM; i++)
- if (mask & (1 << i))
- num_regs++;
-
- gcc_assert (num_regs && num_regs <= 16);
-
- /* We don't record the PC in the dwarf frame information. */
- num_dwarf_regs = num_regs;
- if (mask & (1 << PC_REGNUM))
- num_dwarf_regs--;
-
- /* For the body of the insn we are going to generate an UNSPEC in
- parallel with several USEs. This allows the insn to be recognized
- by the push_multi pattern in the arm.md file. The insn looks
- something like this:
-
- (parallel [
- (set (mem:BLK (pre_dec:BLK (reg:SI sp)))
- (unspec:BLK [(reg:SI r4)] UNSPEC_PUSH_MULT))
- (use (reg:SI 11 fp))
- (use (reg:SI 12 ip))
- (use (reg:SI 14 lr))
- (use (reg:SI 15 pc))
- ])
-
- For the frame note however, we try to be more explicit and actually
- show each register being stored into the stack frame, plus a (single)
- decrement of the stack pointer. We do it this way in order to be
- friendly to the stack unwinding code, which only wants to see a single
- stack decrement per instruction. The RTL we generate for the note looks
- something like this:
-
- (sequence [
- (set (reg:SI sp) (plus:SI (reg:SI sp) (const_int -20)))
- (set (mem:SI (reg:SI sp)) (reg:SI r4))
- (set (mem:SI (plus:SI (reg:SI sp) (const_int 4))) (reg:SI fp))
- (set (mem:SI (plus:SI (reg:SI sp) (const_int 8))) (reg:SI ip))
- (set (mem:SI (plus:SI (reg:SI sp) (const_int 12))) (reg:SI lr))
- ])
-
- This sequence is used both by the code to support stack unwinding for
- exceptions handlers and the code to generate dwarf2 frame debugging. */
-
- par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num_regs));
- dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (num_dwarf_regs + 1));
- dwarf_par_index = 1;
-
- for (i = 0; i <= LAST_ARM_REGNUM; i++)
- {
- if (mask & (1 << i))
- {
- reg = gen_rtx_REG (SImode, i);
-
- XVECEXP (par, 0, 0)
- = gen_rtx_SET (VOIDmode,
- gen_frame_mem (BLKmode,
- gen_rtx_PRE_DEC (BLKmode,
- stack_pointer_rtx)),
- gen_rtx_UNSPEC (BLKmode,
- gen_rtvec (1, reg),
- UNSPEC_PUSH_MULT));
-
- if (i != PC_REGNUM)
- {
- tmp = gen_rtx_SET (VOIDmode,
- gen_frame_mem (SImode, stack_pointer_rtx),
- reg);
- RTX_FRAME_RELATED_P (tmp) = 1;
- XVECEXP (dwarf, 0, dwarf_par_index) = tmp;
- dwarf_par_index++;
- }
-
- break;
- }
- }
-
- for (j = 1, i++; j < num_regs; i++)
- {
- if (mask & (1 << i))
- {
- reg = gen_rtx_REG (SImode, i);
-
- XVECEXP (par, 0, j) = gen_rtx_USE (VOIDmode, reg);
-
- if (i != PC_REGNUM)
- {
- tmp
- = gen_rtx_SET (VOIDmode,
- gen_frame_mem (SImode,
- plus_constant (stack_pointer_rtx,
- 4 * j)),
- reg);
- RTX_FRAME_RELATED_P (tmp) = 1;
- XVECEXP (dwarf, 0, dwarf_par_index++) = tmp;
- }
-
- j++;
- }
- }
-
- par = emit_insn (par);
-
- tmp = gen_rtx_SET (VOIDmode,
- stack_pointer_rtx,
- plus_constant (stack_pointer_rtx, -4 * num_regs));
- RTX_FRAME_RELATED_P (tmp) = 1;
- XVECEXP (dwarf, 0, 0) = tmp;
-
- REG_NOTES (par) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
- REG_NOTES (par));
- return par;
-}
-
-/* Calculate the size of the return value that is passed in registers. */
-static int
-arm_size_return_regs (void)
-{
- enum machine_mode mode;
-
- if (current_function_return_rtx != 0)
- mode = GET_MODE (current_function_return_rtx);
- else
- mode = DECL_MODE (DECL_RESULT (current_function_decl));
-
- return GET_MODE_SIZE (mode);
-}
-
-static rtx
-emit_sfm (int base_reg, int count)
-{
- rtx par;
- rtx dwarf;
- rtx tmp, reg;
- int i;
-
- par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
- dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (count + 1));
-
- reg = gen_rtx_REG (XFmode, base_reg++);
-
- XVECEXP (par, 0, 0)
- = gen_rtx_SET (VOIDmode,
- gen_frame_mem (BLKmode,
- gen_rtx_PRE_DEC (BLKmode,
- stack_pointer_rtx)),
- gen_rtx_UNSPEC (BLKmode,
- gen_rtvec (1, reg),
- UNSPEC_PUSH_MULT));
- tmp = gen_rtx_SET (VOIDmode,
- gen_frame_mem (XFmode, stack_pointer_rtx), reg);
- RTX_FRAME_RELATED_P (tmp) = 1;
- XVECEXP (dwarf, 0, 1) = tmp;
-
- for (i = 1; i < count; i++)
- {
- reg = gen_rtx_REG (XFmode, base_reg++);
- XVECEXP (par, 0, i) = gen_rtx_USE (VOIDmode, reg);
-
- tmp = gen_rtx_SET (VOIDmode,
- gen_frame_mem (XFmode,
- plus_constant (stack_pointer_rtx,
- i * 12)),
- reg);
- RTX_FRAME_RELATED_P (tmp) = 1;
- XVECEXP (dwarf, 0, i + 1) = tmp;
- }
-
- tmp = gen_rtx_SET (VOIDmode,
- stack_pointer_rtx,
- plus_constant (stack_pointer_rtx, -12 * count));
-
- RTX_FRAME_RELATED_P (tmp) = 1;
- XVECEXP (dwarf, 0, 0) = tmp;
-
- par = emit_insn (par);
- REG_NOTES (par) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
- REG_NOTES (par));
- return par;
-}
-
-
-/* Return true if the current function needs to save/restore LR. */
-
-static bool
-thumb_force_lr_save (void)
-{
- return !cfun->machine->lr_save_eliminated
- && (!leaf_function_p ()
- || thumb_far_jump_used_p ()
- || regs_ever_live [LR_REGNUM]);
-}
-
-
-/* Compute the distance from register FROM to register TO.
- These can be the arg pointer (26), the soft frame pointer (25),
- the stack pointer (13) or the hard frame pointer (11).
- In thumb mode r7 is used as the soft frame pointer, if needed.
- Typical stack layout looks like this:
-
- old stack pointer -> | |
- ----
- | | \
- | | saved arguments for
- | | vararg functions
- | | /
- --
- hard FP & arg pointer -> | | \
- | | stack
- | | frame
- | | /
- --
- | | \
- | | call saved
- | | registers
- soft frame pointer -> | | /
- --
- | | \
- | | local
- | | variables
- locals base pointer -> | | /
- --
- | | \
- | | outgoing
- | | arguments
- current stack pointer -> | | /
- --
-
- For a given function some or all of these stack components
- may not be needed, giving rise to the possibility of
- eliminating some of the registers.
-
- The values returned by this function must reflect the behavior
- of arm_expand_prologue() and arm_compute_save_reg_mask().
-
- The sign of the number returned reflects the direction of stack
- growth, so the values are positive for all eliminations except
- from the soft frame pointer to the hard frame pointer.
-
- SFP may point just inside the local variables block to ensure correct
- alignment. */
-
-
-/* Calculate stack offsets. These are used to calculate register elimination
- offsets and in prologue/epilogue code. */
-
-static arm_stack_offsets *
-arm_get_frame_offsets (void)
-{
- struct arm_stack_offsets *offsets;
- unsigned long func_type;
- int leaf;
- int saved;
- HOST_WIDE_INT frame_size;
-
- offsets = &cfun->machine->stack_offsets;
-
- /* We need to know if we are a leaf function. Unfortunately, it
- is possible to be called after start_sequence has been called,
- which causes get_insns to return the insns for the sequence,
- not the function, which will cause leaf_function_p to return
- the incorrect result.
-
- to know about leaf functions once reload has completed, and the
- frame size cannot be changed after that time, so we can safely
- use the cached value. */
-
- if (reload_completed)
- return offsets;
-
- /* Initially this is the size of the local variables. It will translated
- into an offset once we have determined the size of preceding data. */
- frame_size = ROUND_UP_WORD (get_frame_size ());
-
- leaf = leaf_function_p ();
-
- /* Space for variadic functions. */
- offsets->saved_args = current_function_pretend_args_size;
-
- offsets->frame = offsets->saved_args + (frame_pointer_needed ? 4 : 0);
-
- if (TARGET_ARM)
- {
- unsigned int regno;
-
- saved = bit_count (arm_compute_save_reg_mask ()) * 4;
-
- /* We know that SP will be doubleword aligned on entry, and we must
- preserve that condition at any subroutine call. We also require the
- soft frame pointer to be doubleword aligned. */
-
- if (TARGET_REALLY_IWMMXT)
- {
- /* Check for the call-saved iWMMXt registers. */
- for (regno = FIRST_IWMMXT_REGNUM;
- regno <= LAST_IWMMXT_REGNUM;
- regno++)
- if (regs_ever_live [regno] && ! call_used_regs [regno])
- saved += 8;
- }
-
- func_type = arm_current_func_type ();
- if (! IS_VOLATILE (func_type))
- {
- /* Space for saved FPA registers. */
- for (regno = FIRST_FPA_REGNUM; regno <= LAST_FPA_REGNUM; regno++)
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- saved += 12;
-
- /* Space for saved VFP registers. */
- if (TARGET_HARD_FLOAT && TARGET_VFP)
- saved += arm_get_vfp_saved_size ();
- }
- }
- else /* TARGET_THUMB */
- {
- saved = bit_count (thumb_compute_save_reg_mask ()) * 4;
- if (TARGET_BACKTRACE)
- saved += 16;
- }
-
- /* Saved registers include the stack frame. */
- offsets->saved_regs = offsets->saved_args + saved;
- offsets->soft_frame = offsets->saved_regs + CALLER_INTERWORKING_SLOT_SIZE;
- /* A leaf function does not need any stack alignment if it has nothing
- on the stack. */
- if (leaf && frame_size == 0)
- {
- offsets->outgoing_args = offsets->soft_frame;
- offsets->locals_base = offsets->soft_frame;
- return offsets;
- }
-
- /* Ensure SFP has the correct alignment. */
- if (ARM_DOUBLEWORD_ALIGN
- && (offsets->soft_frame & 7))
- offsets->soft_frame += 4;
-
- offsets->locals_base = offsets->soft_frame + frame_size;
- offsets->outgoing_args = (offsets->locals_base
- + current_function_outgoing_args_size);
-
- if (ARM_DOUBLEWORD_ALIGN)
- {
- /* Ensure SP remains doubleword aligned. */
- if (offsets->outgoing_args & 7)
- offsets->outgoing_args += 4;
- gcc_assert (!(offsets->outgoing_args & 7));
- }
-
- return offsets;
-}
-
-
-/* Calculate the relative offsets for the different stack pointers. Positive
- offsets are in the direction of stack growth. */
-
-HOST_WIDE_INT
-arm_compute_initial_elimination_offset (unsigned int from, unsigned int to)
-{
- arm_stack_offsets *offsets;
-
- offsets = arm_get_frame_offsets ();
-
- /* OK, now we have enough information to compute the distances.
- There must be an entry in these switch tables for each pair
- of registers in ELIMINABLE_REGS, even if some of the entries
- seem to be redundant or useless. */
- switch (from)
- {
- case ARG_POINTER_REGNUM:
- switch (to)
- {
- case THUMB_HARD_FRAME_POINTER_REGNUM:
- return 0;
-
- case FRAME_POINTER_REGNUM:
- /* This is the reverse of the soft frame pointer
- to hard frame pointer elimination below. */
- return offsets->soft_frame - offsets->saved_args;
-
- case ARM_HARD_FRAME_POINTER_REGNUM:
- /* If there is no stack frame then the hard
- frame pointer and the arg pointer coincide. */
- if (offsets->frame == offsets->saved_regs)
- return 0;
- /* FIXME: Not sure about this. Maybe we should always return 0 ? */
- return (frame_pointer_needed
- && cfun->static_chain_decl != NULL
- && ! cfun->machine->uses_anonymous_args) ? 4 : 0;
-
- case STACK_POINTER_REGNUM:
- /* If nothing has been pushed on the stack at all
- then this will return -4. This *is* correct! */
- return offsets->outgoing_args - (offsets->saved_args + 4);
-
- default:
- gcc_unreachable ();
- }
- gcc_unreachable ();
-
- case FRAME_POINTER_REGNUM:
- switch (to)
- {
- case THUMB_HARD_FRAME_POINTER_REGNUM:
- return 0;
-
- case ARM_HARD_FRAME_POINTER_REGNUM:
- /* The hard frame pointer points to the top entry in the
- stack frame. The soft frame pointer to the bottom entry
- in the stack frame. If there is no stack frame at all,
- then they are identical. */
-
- return offsets->frame - offsets->soft_frame;
-
- case STACK_POINTER_REGNUM:
- return offsets->outgoing_args - offsets->soft_frame;
-
- default:
- gcc_unreachable ();
- }
- gcc_unreachable ();
-
- default:
- /* You cannot eliminate from the stack pointer.
- In theory you could eliminate from the hard frame
- pointer to the stack pointer, but this will never
- happen, since if a stack frame is not needed the
- hard frame pointer will never be used. */
- gcc_unreachable ();
- }
-}
-
-
-/* Generate the prologue instructions for entry into an ARM function. */
-void
-arm_expand_prologue (void)
-{
- int reg;
- rtx amount;
- rtx insn;
- rtx ip_rtx;
- unsigned long live_regs_mask;
- unsigned long func_type;
- int fp_offset = 0;
- int saved_pretend_args = 0;
- int saved_regs = 0;
- unsigned HOST_WIDE_INT args_to_push;
- arm_stack_offsets *offsets;
-
- func_type = arm_current_func_type ();
-
- /* Naked functions don't have prologues. */
- if (IS_NAKED (func_type))
- return;
-
- /* Make a copy of c_f_p_a_s as we may need to modify it locally. */
- args_to_push = current_function_pretend_args_size;
-
- /* Compute which register we will have to save onto the stack. */
- live_regs_mask = arm_compute_save_reg_mask ();
-
- ip_rtx = gen_rtx_REG (SImode, IP_REGNUM);
-
- if (frame_pointer_needed)
- {
- if (IS_INTERRUPT (func_type))
- {
- /* Interrupt functions must not corrupt any registers.
- Creating a frame pointer however, corrupts the IP
- register, so we must push it first. */
- insn = emit_multi_reg_push (1 << IP_REGNUM);
-
- /* Do not set RTX_FRAME_RELATED_P on this insn.
- The dwarf stack unwinding code only wants to see one
- stack decrement per function, and this is not it. If
- this instruction is labeled as being part of the frame
- creation sequence then dwarf2out_frame_debug_expr will
- die when it encounters the assignment of IP to FP
- later on, since the use of SP here establishes SP as
- the CFA register and not IP.
-
- Anyway this instruction is not really part of the stack
- frame creation although it is part of the prologue. */
- }
- else if (IS_NESTED (func_type))
- {
- /* The Static chain register is the same as the IP register
- used as a scratch register during stack frame creation.
- To get around this need to find somewhere to store IP
- whilst the frame is being created. We try the following
- places in order:
-
- 1. The last argument register.
- 2. A slot on the stack above the frame. (This only
- works if the function is not a varargs function).
- 3. Register r3, after pushing the argument registers
- onto the stack.
-
- Note - we only need to tell the dwarf2 backend about the SP
- adjustment in the second variant; the static chain register
- doesn't need to be unwound, as it doesn't contain a value
- inherited from the caller. */
-
- if (regs_ever_live[3] == 0)
- insn = emit_set_insn (gen_rtx_REG (SImode, 3), ip_rtx);
- else if (args_to_push == 0)
- {
- rtx dwarf;
-
- insn = gen_rtx_PRE_DEC (SImode, stack_pointer_rtx);
- insn = emit_set_insn (gen_frame_mem (SImode, insn), ip_rtx);
- fp_offset = 4;
-
- /* Just tell the dwarf backend that we adjusted SP. */
- dwarf = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
- plus_constant (stack_pointer_rtx,
- -fp_offset));
- RTX_FRAME_RELATED_P (insn) = 1;
- REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
- dwarf, REG_NOTES (insn));
- }
- else
- {
- /* Store the args on the stack. */
- if (cfun->machine->uses_anonymous_args)
- insn = emit_multi_reg_push
- ((0xf0 >> (args_to_push / 4)) & 0xf);
- else
- insn = emit_insn
- (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (- args_to_push)));
-
- RTX_FRAME_RELATED_P (insn) = 1;
-
- saved_pretend_args = 1;
- fp_offset = args_to_push;
- args_to_push = 0;
-
- /* Now reuse r3 to preserve IP. */
- emit_set_insn (gen_rtx_REG (SImode, 3), ip_rtx);
- }
- }
-
- insn = emit_set_insn (ip_rtx,
- plus_constant (stack_pointer_rtx, fp_offset));
- RTX_FRAME_RELATED_P (insn) = 1;
- }
-
- if (args_to_push)
- {
- /* Push the argument registers, or reserve space for them. */
- if (cfun->machine->uses_anonymous_args)
- insn = emit_multi_reg_push
- ((0xf0 >> (args_to_push / 4)) & 0xf);
- else
- insn = emit_insn
- (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (- args_to_push)));
- RTX_FRAME_RELATED_P (insn) = 1;
- }
-
- /* If this is an interrupt service routine, and the link register
- is going to be pushed, and we are not creating a stack frame,
- (which would involve an extra push of IP and a pop in the epilogue)
- subtracting four from LR now will mean that the function return
- can be done with a single instruction. */
- if ((func_type == ARM_FT_ISR || func_type == ARM_FT_FIQ)
- && (live_regs_mask & (1 << LR_REGNUM)) != 0
- && ! frame_pointer_needed)
- {
- rtx lr = gen_rtx_REG (SImode, LR_REGNUM);
-
- emit_set_insn (lr, plus_constant (lr, -4));
- }
-
- if (live_regs_mask)
- {
- insn = emit_multi_reg_push (live_regs_mask);
- saved_regs += bit_count (live_regs_mask) * 4;
- RTX_FRAME_RELATED_P (insn) = 1;
- }
-
- if (TARGET_IWMMXT)
- for (reg = LAST_IWMMXT_REGNUM; reg >= FIRST_IWMMXT_REGNUM; reg--)
- if (regs_ever_live[reg] && ! call_used_regs [reg])
- {
- insn = gen_rtx_PRE_DEC (V2SImode, stack_pointer_rtx);
- insn = gen_frame_mem (V2SImode, insn);
- insn = emit_set_insn (insn, gen_rtx_REG (V2SImode, reg));
- RTX_FRAME_RELATED_P (insn) = 1;
- saved_regs += 8;
- }
-
- if (! IS_VOLATILE (func_type))
- {
- int start_reg;
-
- /* Save any floating point call-saved registers used by this
- function. */
- if (arm_fpu_arch == FPUTYPE_FPA_EMU2)
- {
- for (reg = LAST_FPA_REGNUM; reg >= FIRST_FPA_REGNUM; reg--)
- if (regs_ever_live[reg] && !call_used_regs[reg])
- {
- insn = gen_rtx_PRE_DEC (XFmode, stack_pointer_rtx);
- insn = gen_frame_mem (XFmode, insn);
- insn = emit_set_insn (insn, gen_rtx_REG (XFmode, reg));
- RTX_FRAME_RELATED_P (insn) = 1;
- saved_regs += 12;
- }
- }
- else
- {
- start_reg = LAST_FPA_REGNUM;
-
- for (reg = LAST_FPA_REGNUM; reg >= FIRST_FPA_REGNUM; reg--)
- {
- if (regs_ever_live[reg] && !call_used_regs[reg])
- {
- if (start_reg - reg == 3)
- {
- insn = emit_sfm (reg, 4);
- RTX_FRAME_RELATED_P (insn) = 1;
- saved_regs += 48;
- start_reg = reg - 1;
- }
- }
- else
- {
- if (start_reg != reg)
- {
- insn = emit_sfm (reg + 1, start_reg - reg);
- RTX_FRAME_RELATED_P (insn) = 1;
- saved_regs += (start_reg - reg) * 12;
- }
- start_reg = reg - 1;
- }
- }
-
- if (start_reg != reg)
- {
- insn = emit_sfm (reg + 1, start_reg - reg);
- saved_regs += (start_reg - reg) * 12;
- RTX_FRAME_RELATED_P (insn) = 1;
- }
- }
- if (TARGET_HARD_FLOAT && TARGET_VFP)
- {
- start_reg = FIRST_VFP_REGNUM;
-
- for (reg = FIRST_VFP_REGNUM; reg < LAST_VFP_REGNUM; reg += 2)
- {
- if ((!regs_ever_live[reg] || call_used_regs[reg])
- && (!regs_ever_live[reg + 1] || call_used_regs[reg + 1]))
- {
- if (start_reg != reg)
- saved_regs += vfp_emit_fstmx (start_reg,
- (reg - start_reg) / 2);
- start_reg = reg + 2;
- }
- }
- if (start_reg != reg)
- saved_regs += vfp_emit_fstmx (start_reg,
- (reg - start_reg) / 2);
- }
- }
-
- if (frame_pointer_needed)
- {
- /* Create the new frame pointer. */
- insn = GEN_INT (-(4 + args_to_push + fp_offset));
- insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx, ip_rtx, insn));
- RTX_FRAME_RELATED_P (insn) = 1;
-
- if (IS_NESTED (func_type))
- {
- /* Recover the static chain register. */
- if (regs_ever_live [3] == 0
- || saved_pretend_args)
- insn = gen_rtx_REG (SImode, 3);
- else /* if (current_function_pretend_args_size == 0) */
- {
- insn = plus_constant (hard_frame_pointer_rtx, 4);
- insn = gen_frame_mem (SImode, insn);
- }
-
- emit_set_insn (ip_rtx, insn);
- /* Add a USE to stop propagate_one_insn() from barfing. */
- emit_insn (gen_prologue_use (ip_rtx));
- }
- }
-
- offsets = arm_get_frame_offsets ();
- if (offsets->outgoing_args != offsets->saved_args + saved_regs)
- {
- /* This add can produce multiple insns for a large constant, so we
- need to get tricky. */
- rtx last = get_last_insn ();
-
- amount = GEN_INT (offsets->saved_args + saved_regs
- - offsets->outgoing_args);
-
- insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- amount));
- do
- {
- last = last ? NEXT_INSN (last) : get_insns ();
- RTX_FRAME_RELATED_P (last) = 1;
- }
- while (last != insn);
-
- /* If the frame pointer is needed, emit a special barrier that
- will prevent the scheduler from moving stores to the frame
- before the stack adjustment. */
- if (frame_pointer_needed)
- insn = emit_insn (gen_stack_tie (stack_pointer_rtx,
- hard_frame_pointer_rtx));
- }
-
-
- if (flag_pic && arm_pic_register != INVALID_REGNUM)
- arm_load_pic_register (0UL);
-
- /* If we are profiling, make sure no instructions are scheduled before
- the call to mcount. Similarly if the user has requested no
- scheduling in the prolog. Similarly if we want non-call exceptions
- using the EABI unwinder, to prevent faulting instructions from being
- swapped with a stack adjustment. */
- if (current_function_profile || !TARGET_SCHED_PROLOG
- || (ARM_EABI_UNWIND_TABLES && flag_non_call_exceptions))
- emit_insn (gen_blockage ());
-
- /* If the link register is being kept alive, with the return address in it,
- then make sure that it does not get reused by the ce2 pass. */
- if ((live_regs_mask & (1 << LR_REGNUM)) == 0)
- {
- emit_insn (gen_prologue_use (gen_rtx_REG (SImode, LR_REGNUM)));
- cfun->machine->lr_save_eliminated = 1;
- }
-}
-
-/* If CODE is 'd', then the X is a condition operand and the instruction
- should only be executed if the condition is true.
- if CODE is 'D', then the X is a condition operand and the instruction
- should only be executed if the condition is false: however, if the mode
- of the comparison is CCFPEmode, then always execute the instruction -- we
- do this because in these circumstances !GE does not necessarily imply LT;
- in these cases the instruction pattern will take care to make sure that
- an instruction containing %d will follow, thereby undoing the effects of
- doing this instruction unconditionally.
- If CODE is 'N' then X is a floating point operand that must be negated
- before output.
- If CODE is 'B' then output a bitwise inverted value of X (a const int).
- If X is a REG and CODE is `M', output a ldm/stm style multi-reg. */
-void
-arm_print_operand (FILE *stream, rtx x, int code)
-{
- switch (code)
- {
- case '@':
- fputs (ASM_COMMENT_START, stream);
- return;
-
- case '_':
- fputs (user_label_prefix, stream);
- return;
-
- case '|':
- fputs (REGISTER_PREFIX, stream);
- return;
-
- case '?':
- if (arm_ccfsm_state == 3 || arm_ccfsm_state == 4)
- {
- if (TARGET_THUMB)
- {
- output_operand_lossage ("predicated Thumb instruction");
- break;
- }
- if (current_insn_predicate != NULL)
- {
- output_operand_lossage
- ("predicated instruction in conditional sequence");
- break;
- }
-
- fputs (arm_condition_codes[arm_current_cc], stream);
- }
- else if (current_insn_predicate)
- {
- enum arm_cond_code code;
-
- if (TARGET_THUMB)
- {
- output_operand_lossage ("predicated Thumb instruction");
- break;
- }
-
- code = get_arm_condition_code (current_insn_predicate);
- fputs (arm_condition_codes[code], stream);
- }
- return;
-
- case 'N':
- {
- REAL_VALUE_TYPE r;
- REAL_VALUE_FROM_CONST_DOUBLE (r, x);
- r = REAL_VALUE_NEGATE (r);
- fprintf (stream, "%s", fp_const_from_val (&r));
- }
- return;
-
- case 'B':
- if (GET_CODE (x) == CONST_INT)
- {
- HOST_WIDE_INT val;
- val = ARM_SIGN_EXTEND (~INTVAL (x));
- fprintf (stream, HOST_WIDE_INT_PRINT_DEC, val);
- }
- else
- {
- putc ('~', stream);
- output_addr_const (stream, x);
- }
- return;
-
- case 'i':
- fprintf (stream, "%s", arithmetic_instr (x, 1));
- return;
-
- /* Truncate Cirrus shift counts. */
- case 's':
- if (GET_CODE (x) == CONST_INT)
- {
- fprintf (stream, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0x3f);
- return;
- }
- arm_print_operand (stream, x, 0);
- return;
-
- case 'I':
- fprintf (stream, "%s", arithmetic_instr (x, 0));
- return;
-
- case 'S':
- {
- HOST_WIDE_INT val;
- const char *shift;
-
- if (!shift_operator (x, SImode))
- {
- output_operand_lossage ("invalid shift operand");
- break;
- }
-
- shift = shift_op (x, &val);
-
- if (shift)
- {
- fprintf (stream, ", %s ", shift);
- if (val == -1)
- arm_print_operand (stream, XEXP (x, 1), 0);
- else
- fprintf (stream, "#" HOST_WIDE_INT_PRINT_DEC, val);
- }
- }
- 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 significant 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 significant 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 (GET_CODE (x) != REG || REGNO (x) > LAST_ARM_REGNUM)
- {
- output_operand_lossage ("invalid operand for code '%c'", code);
- return;
- }
-
- asm_fprintf (stream, "%r", REGNO (x) + (WORDS_BIG_ENDIAN ? 1 : 0));
- return;
-
- case 'R':
- if (GET_CODE (x) != REG || REGNO (x) > LAST_ARM_REGNUM)
- {
- output_operand_lossage ("invalid operand for code '%c'", code);
- return;
- }
-
- asm_fprintf (stream, "%r", REGNO (x) + (WORDS_BIG_ENDIAN ? 0 : 1));
- return;
-
- case 'H':
- if (GET_CODE (x) != REG || REGNO (x) > LAST_ARM_REGNUM)
- {
- output_operand_lossage ("invalid operand for code '%c'", code);
- return;
- }
-
- asm_fprintf (stream, "%r", REGNO (x) + 1);
- return;
-
- case 'm':
- asm_fprintf (stream, "%r",
- GET_CODE (XEXP (x, 0)) == REG
- ? REGNO (XEXP (x, 0)) : REGNO (XEXP (XEXP (x, 0), 0)));
- return;
-
- case 'M':
- asm_fprintf (stream, "{%r-%r}",
- REGNO (x),
- REGNO (x) + ARM_NUM_REGS (GET_MODE (x)) - 1);
- return;
-
- case 'd':
- /* CONST_TRUE_RTX means always -- that's the default. */
- if (x == const_true_rtx)
- return;
-
- if (!COMPARISON_P (x))
- {
- output_operand_lossage ("invalid operand for code '%c'", code);
- return;
- }
-
- fputs (arm_condition_codes[get_arm_condition_code (x)],
- stream);
- return;
-
- case 'D':
- /* CONST_TRUE_RTX means not always -- i.e. never. We shouldn't ever
- want to do that. */
- if (x == const_true_rtx)
- {
- output_operand_lossage ("instruction never exectued");
- return;
- }
- if (!COMPARISON_P (x))
- {
- output_operand_lossage ("invalid operand for code '%c'", code);
- return;
- }
-
- fputs (arm_condition_codes[ARM_INVERSE_CONDITION_CODE
- (get_arm_condition_code (x))],
- stream);
- return;
-
- /* Cirrus registers can be accessed in a variety of ways:
- single floating point (f)
- double floating point (d)
- 32bit integer (fx)
- 64bit integer (dx). */
- case 'W': /* Cirrus register in F mode. */
- case 'X': /* Cirrus register in D mode. */
- case 'Y': /* Cirrus register in FX mode. */
- case 'Z': /* Cirrus register in DX mode. */
- gcc_assert (GET_CODE (x) == REG
- && REGNO_REG_CLASS (REGNO (x)) == CIRRUS_REGS);
-
- fprintf (stream, "mv%s%s",
- code == 'W' ? "f"
- : code == 'X' ? "d"
- : code == 'Y' ? "fx" : "dx", reg_names[REGNO (x)] + 2);
-
- return;
-
- /* Print cirrus register in the mode specified by the register's mode. */
- case 'V':
- {
- int mode = GET_MODE (x);
-
- if (GET_CODE (x) != REG || REGNO_REG_CLASS (REGNO (x)) != CIRRUS_REGS)
- {
- output_operand_lossage ("invalid operand for code '%c'", code);
- return;
- }
-
- fprintf (stream, "mv%s%s",
- mode == DFmode ? "d"
- : mode == SImode ? "fx"
- : mode == DImode ? "dx"
- : "f", reg_names[REGNO (x)] + 2);
-
- return;
- }
-
- case 'U':
- if (GET_CODE (x) != REG
- || REGNO (x) < FIRST_IWMMXT_GR_REGNUM
- || REGNO (x) > LAST_IWMMXT_GR_REGNUM)
- /* Bad value for wCG register number. */
- {
- output_operand_lossage ("invalid operand for code '%c'", code);
- return;
- }
-
- else
- fprintf (stream, "%d", REGNO (x) - FIRST_IWMMXT_GR_REGNUM);
- return;
-
- /* Print an iWMMXt control register name. */
- case 'w':
- if (GET_CODE (x) != CONST_INT
- || INTVAL (x) < 0
- || INTVAL (x) >= 16)
- /* Bad value for wC register number. */
- {
- output_operand_lossage ("invalid operand for code '%c'", code);
- return;
- }
-
- else
- {
- static const char * wc_reg_names [16] =
- {
- "wCID", "wCon", "wCSSF", "wCASF",
- "wC4", "wC5", "wC6", "wC7",
- "wCGR0", "wCGR1", "wCGR2", "wCGR3",
- "wC12", "wC13", "wC14", "wC15"
- };
-
- fprintf (stream, wc_reg_names [INTVAL (x)]);
- }
- return;
-
- /* Print a VFP double precision register name. */
- case 'P':
- {
- int mode = GET_MODE (x);
- int num;
-
- if (mode != DImode && mode != DFmode)
- {
- output_operand_lossage ("invalid operand for code '%c'", code);
- return;
- }
-
- if (GET_CODE (x) != REG
- || !IS_VFP_REGNUM (REGNO (x)))
- {
- output_operand_lossage ("invalid operand for code '%c'", code);
- return;
- }
-
- num = REGNO(x) - FIRST_VFP_REGNUM;
- if (num & 1)
- {
- output_operand_lossage ("invalid operand for code '%c'", code);
- return;
- }
-
- fprintf (stream, "d%d", num >> 1);
- }
- return;
-
- default:
- if (x == 0)
- {
- output_operand_lossage ("missing operand");
- return;
- }
-
- switch (GET_CODE (x))
- {
- case REG:
- asm_fprintf (stream, "%r", REGNO (x));
- break;
-
- case MEM:
- output_memory_reference_mode = GET_MODE (x);
- output_address (XEXP (x, 0));
- break;
-
- case CONST_DOUBLE:
- fprintf (stream, "#%s", fp_immediate_constant (x));
- break;
-
- default:
- gcc_assert (GET_CODE (x) != NEG);
- fputc ('#', stream);
- output_addr_const (stream, x);
- break;
- }
- }
-}
-
-#ifndef AOF_ASSEMBLER
-/* Target hook for assembling integer objects. The ARM version needs to
- handle word-sized values specially. */
-static bool
-arm_assemble_integer (rtx x, unsigned int size, int aligned_p)
-{
- if (size == UNITS_PER_WORD && aligned_p)
- {
- fputs ("\t.word\t", asm_out_file);
- output_addr_const (asm_out_file, x);
-
- /* Mark symbols as position independent. We only do this in the
- .text segment, not in the .data segment. */
- if (NEED_GOT_RELOC && flag_pic && making_const_table &&
- (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF))
- {
- if (GET_CODE (x) == SYMBOL_REF
- && (CONSTANT_POOL_ADDRESS_P (x)
- || SYMBOL_REF_LOCAL_P (x)))
- fputs ("(GOTOFF)", asm_out_file);
- else if (GET_CODE (x) == LABEL_REF)
- fputs ("(GOTOFF)", asm_out_file);
- else
- fputs ("(GOT)", asm_out_file);
- }
- fputc ('\n', asm_out_file);
- return true;
- }
-
- if (arm_vector_mode_supported_p (GET_MODE (x)))
- {
- int i, units;
-
- gcc_assert (GET_CODE (x) == CONST_VECTOR);
-
- units = CONST_VECTOR_NUNITS (x);
-
- switch (GET_MODE (x))
- {
- case V2SImode: size = 4; break;
- case V4HImode: size = 2; break;
- case V8QImode: size = 1; break;
- default:
- gcc_unreachable ();
- }
-
- for (i = 0; i < units; i++)
- {
- rtx elt;
-
- elt = CONST_VECTOR_ELT (x, i);
- assemble_integer
- (elt, size, i == 0 ? BIGGEST_ALIGNMENT : size * BITS_PER_UNIT, 1);
- }
-
- return true;
- }
-
- return default_assemble_integer (x, size, aligned_p);
-}
-
-
-/* Add a function to the list of static constructors. */
-
-static void
-arm_elf_asm_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
-{
- if (!TARGET_AAPCS_BASED)
- {
- default_named_section_asm_out_constructor (symbol, priority);
- return;
- }
-
- /* Put these in the .init_array section, using a special relocation. */
- switch_to_section (ctors_section);
- assemble_align (POINTER_SIZE);
- fputs ("\t.word\t", asm_out_file);
- output_addr_const (asm_out_file, symbol);
- fputs ("(target1)\n", asm_out_file);
-}
-#endif
-
-/* A finite state machine takes care of noticing whether or not instructions
- can be conditionally executed, and thus decrease execution time and code
- size by deleting branch instructions. The fsm is controlled by
- final_prescan_insn, and controls the actions of ASM_OUTPUT_OPCODE. */
-
-/* The state of the fsm controlling condition codes are:
- 0: normal, do nothing special
- 1: make ASM_OUTPUT_OPCODE not output this instruction
- 2: make ASM_OUTPUT_OPCODE not output this instruction
- 3: make instructions conditional
- 4: make instructions conditional
-
- State transitions (state->state by whom under condition):
- 0 -> 1 final_prescan_insn if the `target' is a label
- 0 -> 2 final_prescan_insn if the `target' is an unconditional branch
- 1 -> 3 ASM_OUTPUT_OPCODE after not having output the conditional branch
- 2 -> 4 ASM_OUTPUT_OPCODE after not having output the conditional branch
- 3 -> 0 (*targetm.asm_out.internal_label) if the `target' label is reached
- (the target label has CODE_LABEL_NUMBER equal to arm_target_label).
- 4 -> 0 final_prescan_insn if the `target' unconditional branch is reached
- (the target insn is arm_target_insn).
-
- If the jump clobbers the conditions then we use states 2 and 4.
-
- A similar thing can be done with conditional return insns.
-
- XXX In case the `target' is an unconditional branch, this conditionalising
- of the instructions always reduces code size, but not always execution
- time. But then, I want to reduce the code size to somewhere near what
- /bin/cc produces. */
-
-/* Returns the index of the ARM condition code string in
- `arm_condition_codes'. COMPARISON should be an rtx like
- `(eq (...) (...))'. */
-static enum arm_cond_code
-get_arm_condition_code (rtx comparison)
-{
- enum machine_mode mode = GET_MODE (XEXP (comparison, 0));
- int code;
- enum rtx_code comp_code = GET_CODE (comparison);
-
- if (GET_MODE_CLASS (mode) != MODE_CC)
- mode = SELECT_CC_MODE (comp_code, XEXP (comparison, 0),
- XEXP (comparison, 1));
-
- switch (mode)
- {
- case CC_DNEmode: code = ARM_NE; goto dominance;
- case CC_DEQmode: code = ARM_EQ; goto dominance;
- case CC_DGEmode: code = ARM_GE; goto dominance;
- case CC_DGTmode: code = ARM_GT; goto dominance;
- case CC_DLEmode: code = ARM_LE; goto dominance;
- case CC_DLTmode: code = ARM_LT; goto dominance;
- case CC_DGEUmode: code = ARM_CS; goto dominance;
- case CC_DGTUmode: code = ARM_HI; goto dominance;
- case CC_DLEUmode: code = ARM_LS; goto dominance;
- case CC_DLTUmode: code = ARM_CC;
-
- dominance:
- gcc_assert (comp_code == EQ || comp_code == NE);
-
- if (comp_code == EQ)
- return ARM_INVERSE_CONDITION_CODE (code);
- return code;
-
- case CC_NOOVmode:
- switch (comp_code)
- {
- case NE: return ARM_NE;
- case EQ: return ARM_EQ;
- case GE: return ARM_PL;
- case LT: return ARM_MI;
- default: gcc_unreachable ();
- }
-
- case CC_Zmode:
- switch (comp_code)
- {
- case NE: return ARM_NE;
- case EQ: return ARM_EQ;
- default: gcc_unreachable ();
- }
-
- case CC_Nmode:
- switch (comp_code)
- {
- case NE: return ARM_MI;
- case EQ: return ARM_PL;
- default: gcc_unreachable ();
- }
-
- case CCFPEmode:
- case CCFPmode:
- /* These encodings assume that AC=1 in the FPA system control
- byte. This allows us to handle all cases except UNEQ and
- LTGT. */
- switch (comp_code)
- {
- case GE: return ARM_GE;
- case GT: return ARM_GT;
- case LE: return ARM_LS;
- case LT: return ARM_MI;
- case NE: return ARM_NE;
- case EQ: return ARM_EQ;
- case ORDERED: return ARM_VC;
- case UNORDERED: return ARM_VS;
- case UNLT: return ARM_LT;
- case UNLE: return ARM_LE;
- case UNGT: return ARM_HI;
- case UNGE: return ARM_PL;
- /* UNEQ and LTGT do not have a representation. */
- case UNEQ: /* Fall through. */
- case LTGT: /* Fall through. */
- default: gcc_unreachable ();
- }
-
- case CC_SWPmode:
- switch (comp_code)
- {
- case NE: return ARM_NE;
- case EQ: return ARM_EQ;
- case GE: return ARM_LE;
- case GT: return ARM_LT;
- case LE: return ARM_GE;
- case LT: return ARM_GT;
- case GEU: return ARM_LS;
- case GTU: return ARM_CC;
- case LEU: return ARM_CS;
- case LTU: return ARM_HI;
- default: gcc_unreachable ();
- }
-
- case CC_Cmode:
- switch (comp_code)
- {
- case LTU: return ARM_CS;
- case GEU: return ARM_CC;
- default: gcc_unreachable ();
- }
-
- case CCmode:
- switch (comp_code)
- {
- case NE: return ARM_NE;
- case EQ: return ARM_EQ;
- case GE: return ARM_GE;
- case GT: return ARM_GT;
- case LE: return ARM_LE;
- case LT: return ARM_LT;
- case GEU: return ARM_CS;
- case GTU: return ARM_HI;
- case LEU: return ARM_LS;
- case LTU: return ARM_CC;
- default: gcc_unreachable ();
- }
-
- default: gcc_unreachable ();
- }
-}
-
-void
-arm_final_prescan_insn (rtx insn)
-{
- /* BODY will hold the body of INSN. */
- rtx body = PATTERN (insn);
-
- /* This will be 1 if trying to repeat the trick, and things need to be
- reversed if it appears to fail. */
- int reverse = 0;
-
- /* JUMP_CLOBBERS will be one implies that the conditions if a branch is
- taken are clobbered, even if the rtl suggests otherwise. It also
- means that we have to grub around within the jump expression to find
- out what the conditions are when the jump isn't taken. */
- int jump_clobbers = 0;
-
- /* If we start with a return insn, we only succeed if we find another one. */
- int seeking_return = 0;
-
- /* START_INSN will hold the insn from where we start looking. This is the
- first insn after the following code_label if REVERSE is true. */
- rtx start_insn = insn;
-
- /* If in state 4, check if the target branch is reached, in order to
- change back to state 0. */
- if (arm_ccfsm_state == 4)
- {
- if (insn == arm_target_insn)
- {
- arm_target_insn = NULL;
- arm_ccfsm_state = 0;
- }
- return;
- }
-
- /* If in state 3, it is possible to repeat the trick, if this insn is an
- unconditional branch to a label, and immediately following this branch
- is the previous target label which is only used once, and the label this
- branch jumps to is not too far off. */
- if (arm_ccfsm_state == 3)
- {
- if (simplejump_p (insn))
- {
- start_insn = next_nonnote_insn (start_insn);
- if (GET_CODE (start_insn) == BARRIER)
- {
- /* XXX Isn't this always a barrier? */
- start_insn = next_nonnote_insn (start_insn);
- }
- if (GET_CODE (start_insn) == CODE_LABEL
- && CODE_LABEL_NUMBER (start_insn) == arm_target_label
- && LABEL_NUSES (start_insn) == 1)
- reverse = TRUE;
- else
- return;
- }
- else if (GET_CODE (body) == RETURN)
- {
- start_insn = next_nonnote_insn (start_insn);
- if (GET_CODE (start_insn) == BARRIER)
- start_insn = next_nonnote_insn (start_insn);
- if (GET_CODE (start_insn) == CODE_LABEL
- && CODE_LABEL_NUMBER (start_insn) == arm_target_label
- && LABEL_NUSES (start_insn) == 1)
- {
- reverse = TRUE;
- seeking_return = 1;
- }
- else
- return;
- }
- else
- return;
- }
-
- gcc_assert (!arm_ccfsm_state || reverse);
- if (GET_CODE (insn) != JUMP_INSN)
- return;
-
- /* This jump might be paralleled with a clobber of the condition codes
- the jump should always come first */
- if (GET_CODE (body) == PARALLEL && XVECLEN (body, 0) > 0)
- body = XVECEXP (body, 0, 0);
-
- if (reverse
- || (GET_CODE (body) == SET && GET_CODE (SET_DEST (body)) == PC
- && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE))
- {
- int insns_skipped;
- int fail = FALSE, succeed = FALSE;
- /* Flag which part of the IF_THEN_ELSE is the LABEL_REF. */
- int then_not_else = TRUE;
- rtx this_insn = start_insn, label = 0;
-
- /* If the jump cannot be done with one instruction, we cannot
- conditionally execute the instruction in the inverse case. */
- if (get_attr_conds (insn) == CONDS_JUMP_CLOB)
- {
- jump_clobbers = 1;
- return;
- }
-
- /* Register the insn jumped to. */
- if (reverse)
- {
- if (!seeking_return)
- label = XEXP (SET_SRC (body), 0);
- }
- else if (GET_CODE (XEXP (SET_SRC (body), 1)) == LABEL_REF)
- label = XEXP (XEXP (SET_SRC (body), 1), 0);
- else if (GET_CODE (XEXP (SET_SRC (body), 2)) == LABEL_REF)
- {
- label = XEXP (XEXP (SET_SRC (body), 2), 0);
- then_not_else = FALSE;
- }
- else if (GET_CODE (XEXP (SET_SRC (body), 1)) == RETURN)
- seeking_return = 1;
- else if (GET_CODE (XEXP (SET_SRC (body), 2)) == RETURN)
- {
- seeking_return = 1;
- then_not_else = FALSE;
- }
- else
- gcc_unreachable ();
-
- /* See how many insns this branch skips, and what kind of insns. If all
- insns are okay, and the label or unconditional branch to the same
- label is not too far away, succeed. */
- for (insns_skipped = 0;
- !fail && !succeed && insns_skipped++ < max_insns_skipped;)
- {
- rtx scanbody;
-
- this_insn = next_nonnote_insn (this_insn);
- if (!this_insn)
- break;
-
- switch (GET_CODE (this_insn))
- {
- case CODE_LABEL:
- /* Succeed if it is the target label, otherwise fail since
- control falls in from somewhere else. */
- if (this_insn == label)
- {
- if (jump_clobbers)
- {
- arm_ccfsm_state = 2;
- this_insn = next_nonnote_insn (this_insn);
- }
- else
- arm_ccfsm_state = 1;
- succeed = TRUE;
- }
- else
- fail = TRUE;
- break;
-
- case BARRIER:
- /* Succeed if the following insn is the target label.
- Otherwise fail.
- If return insns are used then the last insn in a function
- will be a barrier. */
- this_insn = next_nonnote_insn (this_insn);
- if (this_insn && this_insn == label)
- {
- if (jump_clobbers)
- {
- arm_ccfsm_state = 2;
- this_insn = next_nonnote_insn (this_insn);
- }
- else
- arm_ccfsm_state = 1;
- succeed = TRUE;
- }
- else
- fail = TRUE;
- break;
-
- case CALL_INSN:
- /* The AAPCS says that conditional calls should not be
- used since they make interworking inefficient (the
- linker can't transform BL<cond> into BLX). That's
- only a problem if the machine has BLX. */
- if (arm_arch5)
- {
- fail = TRUE;
- break;
- }
-
- /* Succeed if the following insn is the target label, or
- if the following two insns are a barrier and the
- target label. */
- this_insn = next_nonnote_insn (this_insn);
- if (this_insn && GET_CODE (this_insn) == BARRIER)
- this_insn = next_nonnote_insn (this_insn);
-
- if (this_insn && this_insn == label
- && insns_skipped < max_insns_skipped)
- {
- if (jump_clobbers)
- {
- arm_ccfsm_state = 2;
- this_insn = next_nonnote_insn (this_insn);
- }
- else
- arm_ccfsm_state = 1;
- succeed = TRUE;
- }
- else
- fail = TRUE;
- break;
-
- case JUMP_INSN:
- /* If this is an unconditional branch to the same label, succeed.
- If it is to another label, do nothing. If it is conditional,
- fail. */
- /* XXX Probably, the tests for SET and the PC are
- unnecessary. */
-
- scanbody = PATTERN (this_insn);
- if (GET_CODE (scanbody) == SET
- && GET_CODE (SET_DEST (scanbody)) == PC)
- {
- if (GET_CODE (SET_SRC (scanbody)) == LABEL_REF
- && XEXP (SET_SRC (scanbody), 0) == label && !reverse)
- {
- arm_ccfsm_state = 2;
- succeed = TRUE;
- }
- else if (GET_CODE (SET_SRC (scanbody)) == IF_THEN_ELSE)
- fail = TRUE;
- }
- /* Fail if a conditional return is undesirable (e.g. on a
- StrongARM), but still allow this if optimizing for size. */
- else if (GET_CODE (scanbody) == RETURN
- && !use_return_insn (TRUE, NULL)
- && !optimize_size)
- fail = TRUE;
- else if (GET_CODE (scanbody) == RETURN
- && seeking_return)
- {
- arm_ccfsm_state = 2;
- succeed = TRUE;
- }
- else if (GET_CODE (scanbody) == PARALLEL)
- {
- switch (get_attr_conds (this_insn))
- {
- case CONDS_NOCOND:
- break;
- default:
- fail = TRUE;
- break;
- }
- }
- else
- fail = TRUE; /* Unrecognized jump (e.g. epilogue). */
-
- break;
-
- case INSN:
- /* Instructions using or affecting the condition codes make it
- fail. */
- scanbody = PATTERN (this_insn);
- if (!(GET_CODE (scanbody) == SET
- || GET_CODE (scanbody) == PARALLEL)
- || get_attr_conds (this_insn) != CONDS_NOCOND)
- fail = TRUE;
-
- /* A conditional cirrus instruction must be followed by
- a non Cirrus instruction. However, since we
- conditionalize instructions in this function and by
- the time we get here we can't add instructions
- (nops), because shorten_branches() has already been
- called, we will disable conditionalizing Cirrus
- instructions to be safe. */
- if (GET_CODE (scanbody) != USE
- && GET_CODE (scanbody) != CLOBBER
- && get_attr_cirrus (this_insn) != CIRRUS_NOT)
- fail = TRUE;
- break;
-
- default:
- break;
- }
- }
- if (succeed)
- {
- if ((!seeking_return) && (arm_ccfsm_state == 1 || reverse))
- arm_target_label = CODE_LABEL_NUMBER (label);
- else
- {
- gcc_assert (seeking_return || arm_ccfsm_state == 2);
-
- while (this_insn && GET_CODE (PATTERN (this_insn)) == USE)
- {
- this_insn = next_nonnote_insn (this_insn);
- gcc_assert (!this_insn
- || (GET_CODE (this_insn) != BARRIER
- && GET_CODE (this_insn) != CODE_LABEL));
- }
- if (!this_insn)
- {
- /* Oh, dear! we ran off the end.. give up. */
- recog (PATTERN (insn), insn, NULL);
- arm_ccfsm_state = 0;
- arm_target_insn = NULL;
- return;
- }
- arm_target_insn = this_insn;
- }
- if (jump_clobbers)
- {
- gcc_assert (!reverse);
- arm_current_cc =
- get_arm_condition_code (XEXP (XEXP (XEXP (SET_SRC (body),
- 0), 0), 1));
- if (GET_CODE (XEXP (XEXP (SET_SRC (body), 0), 0)) == AND)
- arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
- if (GET_CODE (XEXP (SET_SRC (body), 0)) == NE)
- arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
- }
- else
- {
- /* If REVERSE is true, ARM_CURRENT_CC needs to be inverted from
- what it was. */
- if (!reverse)
- arm_current_cc = get_arm_condition_code (XEXP (SET_SRC (body),
- 0));
- }
-
- if (reverse || then_not_else)
- arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
- }
-
- /* Restore recog_data (getting the attributes of other insns can
- destroy this array, but final.c assumes that it remains intact
- across this call; since the insn has been recognized already we
- call recog direct). */
- recog (PATTERN (insn), insn, NULL);
- }
-}
-
-/* Returns true if REGNO is a valid register
- for holding a quantity of type MODE. */
-int
-arm_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
-{
- if (GET_MODE_CLASS (mode) == MODE_CC)
- return (regno == CC_REGNUM
- || (TARGET_HARD_FLOAT && TARGET_VFP
- && regno == VFPCC_REGNUM));
-
- if (TARGET_THUMB)
- /* For the Thumb we only allow values bigger than SImode in
- registers 0 - 6, so that there is always a second low
- register available to hold the upper part of the value.
- We probably we ought to ensure that the register is the
- start of an even numbered register pair. */
- return (ARM_NUM_REGS (mode) < 2) || (regno < LAST_LO_REGNUM);
-
- if (TARGET_HARD_FLOAT && TARGET_MAVERICK
- && IS_CIRRUS_REGNUM (regno))
- /* We have outlawed SI values in Cirrus registers because they
- reside in the lower 32 bits, but SF values reside in the
- upper 32 bits. This causes gcc all sorts of grief. We can't
- even split the registers into pairs because Cirrus SI values
- get sign extended to 64bits-- aldyh. */
- return (GET_MODE_CLASS (mode) == MODE_FLOAT) || (mode == DImode);
-
- if (TARGET_HARD_FLOAT && TARGET_VFP
- && IS_VFP_REGNUM (regno))
- {
- if (mode == SFmode || mode == SImode)
- return TRUE;
-
- /* DFmode values are only valid in even register pairs. */
- if (mode == DFmode)
- return ((regno - FIRST_VFP_REGNUM) & 1) == 0;
- return FALSE;
- }
-
- if (TARGET_REALLY_IWMMXT)
- {
- if (IS_IWMMXT_GR_REGNUM (regno))
- return mode == SImode;
-
- if (IS_IWMMXT_REGNUM (regno))
- return VALID_IWMMXT_REG_MODE (mode);
- }
-
- /* We allow any value to be stored in the general registers.
- Restrict doubleword quantities to even register pairs so that we can
- use ldrd. */
- if (regno <= LAST_ARM_REGNUM)
- return !(TARGET_LDRD && GET_MODE_SIZE (mode) > 4 && (regno & 1) != 0);
-
- if (regno == FRAME_POINTER_REGNUM
- || regno == ARG_POINTER_REGNUM)
- /* We only allow integers in the fake hard registers. */
- return GET_MODE_CLASS (mode) == MODE_INT;
-
- /* The only registers left are the FPA registers
- which we only allow to hold FP values. */
- return (TARGET_HARD_FLOAT && TARGET_FPA
- && GET_MODE_CLASS (mode) == MODE_FLOAT
- && regno >= FIRST_FPA_REGNUM
- && regno <= LAST_FPA_REGNUM);
-}
-
-int
-arm_regno_class (int regno)
-{
- if (TARGET_THUMB)
- {
- if (regno == STACK_POINTER_REGNUM)
- return STACK_REG;
- if (regno == CC_REGNUM)
- return CC_REG;
- if (regno < 8)
- return LO_REGS;
- return HI_REGS;
- }
-
- if ( regno <= LAST_ARM_REGNUM
- || regno == FRAME_POINTER_REGNUM
- || regno == ARG_POINTER_REGNUM)
- return GENERAL_REGS;
-
- if (regno == CC_REGNUM || regno == VFPCC_REGNUM)
- return NO_REGS;
-
- if (IS_CIRRUS_REGNUM (regno))
- return CIRRUS_REGS;
-
- if (IS_VFP_REGNUM (regno))
- return VFP_REGS;
-
- if (IS_IWMMXT_REGNUM (regno))
- return IWMMXT_REGS;
-
- if (IS_IWMMXT_GR_REGNUM (regno))
- return IWMMXT_GR_REGS;
-
- return FPA_REGS;
-}
-
-/* Handle a special case when computing the offset
- of an argument from the frame pointer. */
-int
-arm_debugger_arg_offset (int value, rtx addr)
-{
- rtx insn;
-
- /* We are only interested if dbxout_parms() failed to compute the offset. */
- if (value != 0)
- return 0;
-
- /* We can only cope with the case where the address is held in a register. */
- if (GET_CODE (addr) != REG)
- return 0;
-
- /* If we are using the frame pointer to point at the argument, then
- an offset of 0 is correct. */
- if (REGNO (addr) == (unsigned) HARD_FRAME_POINTER_REGNUM)
- return 0;
-
- /* If we are using the stack pointer to point at the
- argument, then an offset of 0 is correct. */
- if ((TARGET_THUMB || !frame_pointer_needed)
- && REGNO (addr) == SP_REGNUM)
- return 0;
-
- /* Oh dear. The argument is pointed to by a register rather
- than being held in a register, or being stored at a known
- offset from the frame pointer. Since GDB only understands
- those two kinds of argument we must translate the address
- held in the register into an offset from the frame pointer.
- We do this by searching through the insns for the function
- looking to see where this register gets its value. If the
- register is initialized from the frame pointer plus an offset
- then we are in luck and we can continue, otherwise we give up.
-
- This code is exercised by producing debugging information
- for a function with arguments like this:
-
- double func (double a, double b, int c, double d) {return d;}
-
- Without this code the stab for parameter 'd' will be set to
- an offset of 0 from the frame pointer, rather than 8. */
-
- /* The if() statement says:
-
- If the insn is a normal instruction
- and if the insn is setting the value in a register
- and if the register being set is the register holding the address of the argument
- and if the address is computing by an addition
- that involves adding to a register
- which is the frame pointer
- a constant integer
-
- then... */
-
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- {
- if ( GET_CODE (insn) == INSN
- && GET_CODE (PATTERN (insn)) == SET
- && REGNO (XEXP (PATTERN (insn), 0)) == REGNO (addr)
- && GET_CODE (XEXP (PATTERN (insn), 1)) == PLUS
- && GET_CODE (XEXP (XEXP (PATTERN (insn), 1), 0)) == REG
- && REGNO (XEXP (XEXP (PATTERN (insn), 1), 0)) == (unsigned) HARD_FRAME_POINTER_REGNUM
- && GET_CODE (XEXP (XEXP (PATTERN (insn), 1), 1)) == CONST_INT
- )
- {
- value = INTVAL (XEXP (XEXP (PATTERN (insn), 1), 1));
-
- break;
- }
- }
-
- if (value == 0)
- {
- debug_rtx (addr);
- warning (0, "unable to compute real location of stacked parameter");
- value = 8; /* XXX magic hack */
- }
-
- return value;
-}
-
-#define def_mbuiltin(MASK, NAME, TYPE, CODE) \
- do \
- { \
- if ((MASK) & insn_flags) \
- lang_hooks.builtin_function ((NAME), (TYPE), (CODE), \
- BUILT_IN_MD, NULL, NULL_TREE); \
- } \
- while (0)
-
-struct builtin_description
-{
- const unsigned int mask;
- const enum insn_code icode;
- const char * const name;
- const enum arm_builtins code;
- const enum rtx_code comparison;
- const unsigned int flag;
-};
-
-static const struct builtin_description bdesc_2arg[] =
-{
-#define IWMMXT_BUILTIN(code, string, builtin) \
- { FL_IWMMXT, CODE_FOR_##code, "__builtin_arm_" string, \
- ARM_BUILTIN_##builtin, 0, 0 },
-
- IWMMXT_BUILTIN (addv8qi3, "waddb", WADDB)
- IWMMXT_BUILTIN (addv4hi3, "waddh", WADDH)
- IWMMXT_BUILTIN (addv2si3, "waddw", WADDW)
- IWMMXT_BUILTIN (subv8qi3, "wsubb", WSUBB)
- IWMMXT_BUILTIN (subv4hi3, "wsubh", WSUBH)
- IWMMXT_BUILTIN (subv2si3, "wsubw", WSUBW)
- IWMMXT_BUILTIN (ssaddv8qi3, "waddbss", WADDSSB)
- IWMMXT_BUILTIN (ssaddv4hi3, "waddhss", WADDSSH)
- IWMMXT_BUILTIN (ssaddv2si3, "waddwss", WADDSSW)
- IWMMXT_BUILTIN (sssubv8qi3, "wsubbss", WSUBSSB)
- IWMMXT_BUILTIN (sssubv4hi3, "wsubhss", WSUBSSH)
- IWMMXT_BUILTIN (sssubv2si3, "wsubwss", WSUBSSW)
- IWMMXT_BUILTIN (usaddv8qi3, "waddbus", WADDUSB)
- IWMMXT_BUILTIN (usaddv4hi3, "waddhus", WADDUSH)
- IWMMXT_BUILTIN (usaddv2si3, "waddwus", WADDUSW)
- IWMMXT_BUILTIN (ussubv8qi3, "wsubbus", WSUBUSB)
- IWMMXT_BUILTIN (ussubv4hi3, "wsubhus", WSUBUSH)
- IWMMXT_BUILTIN (ussubv2si3, "wsubwus", WSUBUSW)
- IWMMXT_BUILTIN (mulv4hi3, "wmulul", WMULUL)
- IWMMXT_BUILTIN (smulv4hi3_highpart, "wmulsm", WMULSM)
- IWMMXT_BUILTIN (umulv4hi3_highpart, "wmulum", WMULUM)
- IWMMXT_BUILTIN (eqv8qi3, "wcmpeqb", WCMPEQB)
- IWMMXT_BUILTIN (eqv4hi3, "wcmpeqh", WCMPEQH)
- IWMMXT_BUILTIN (eqv2si3, "wcmpeqw", WCMPEQW)
- IWMMXT_BUILTIN (gtuv8qi3, "wcmpgtub", WCMPGTUB)
- IWMMXT_BUILTIN (gtuv4hi3, "wcmpgtuh", WCMPGTUH)
- IWMMXT_BUILTIN (gtuv2si3, "wcmpgtuw", WCMPGTUW)
- IWMMXT_BUILTIN (gtv8qi3, "wcmpgtsb", WCMPGTSB)
- IWMMXT_BUILTIN (gtv4hi3, "wcmpgtsh", WCMPGTSH)
- IWMMXT_BUILTIN (gtv2si3, "wcmpgtsw", WCMPGTSW)
- IWMMXT_BUILTIN (umaxv8qi3, "wmaxub", WMAXUB)
- IWMMXT_BUILTIN (smaxv8qi3, "wmaxsb", WMAXSB)
- IWMMXT_BUILTIN (umaxv4hi3, "wmaxuh", WMAXUH)
- IWMMXT_BUILTIN (smaxv4hi3, "wmaxsh", WMAXSH)
- IWMMXT_BUILTIN (umaxv2si3, "wmaxuw", WMAXUW)
- IWMMXT_BUILTIN (smaxv2si3, "wmaxsw", WMAXSW)
- IWMMXT_BUILTIN (uminv8qi3, "wminub", WMINUB)
- IWMMXT_BUILTIN (sminv8qi3, "wminsb", WMINSB)
- IWMMXT_BUILTIN (uminv4hi3, "wminuh", WMINUH)
- IWMMXT_BUILTIN (sminv4hi3, "wminsh", WMINSH)
- IWMMXT_BUILTIN (uminv2si3, "wminuw", WMINUW)
- IWMMXT_BUILTIN (sminv2si3, "wminsw", WMINSW)
- IWMMXT_BUILTIN (iwmmxt_anddi3, "wand", WAND)
- IWMMXT_BUILTIN (iwmmxt_nanddi3, "wandn", WANDN)
- IWMMXT_BUILTIN (iwmmxt_iordi3, "wor", WOR)
- IWMMXT_BUILTIN (iwmmxt_xordi3, "wxor", WXOR)
- IWMMXT_BUILTIN (iwmmxt_uavgv8qi3, "wavg2b", WAVG2B)
- IWMMXT_BUILTIN (iwmmxt_uavgv4hi3, "wavg2h", WAVG2H)
- IWMMXT_BUILTIN (iwmmxt_uavgrndv8qi3, "wavg2br", WAVG2BR)
- IWMMXT_BUILTIN (iwmmxt_uavgrndv4hi3, "wavg2hr", WAVG2HR)
- IWMMXT_BUILTIN (iwmmxt_wunpckilb, "wunpckilb", WUNPCKILB)
- IWMMXT_BUILTIN (iwmmxt_wunpckilh, "wunpckilh", WUNPCKILH)
- IWMMXT_BUILTIN (iwmmxt_wunpckilw, "wunpckilw", WUNPCKILW)
- IWMMXT_BUILTIN (iwmmxt_wunpckihb, "wunpckihb", WUNPCKIHB)
- IWMMXT_BUILTIN (iwmmxt_wunpckihh, "wunpckihh", WUNPCKIHH)
- IWMMXT_BUILTIN (iwmmxt_wunpckihw, "wunpckihw", WUNPCKIHW)
- IWMMXT_BUILTIN (iwmmxt_wmadds, "wmadds", WMADDS)
- IWMMXT_BUILTIN (iwmmxt_wmaddu, "wmaddu", WMADDU)
-
-#define IWMMXT_BUILTIN2(code, builtin) \
- { FL_IWMMXT, CODE_FOR_##code, NULL, ARM_BUILTIN_##builtin, 0, 0 },
-
- IWMMXT_BUILTIN2 (iwmmxt_wpackhss, WPACKHSS)
- IWMMXT_BUILTIN2 (iwmmxt_wpackwss, WPACKWSS)
- IWMMXT_BUILTIN2 (iwmmxt_wpackdss, WPACKDSS)
- IWMMXT_BUILTIN2 (iwmmxt_wpackhus, WPACKHUS)
- IWMMXT_BUILTIN2 (iwmmxt_wpackwus, WPACKWUS)
- IWMMXT_BUILTIN2 (iwmmxt_wpackdus, WPACKDUS)
- IWMMXT_BUILTIN2 (ashlv4hi3_di, WSLLH)
- IWMMXT_BUILTIN2 (ashlv4hi3, WSLLHI)
- IWMMXT_BUILTIN2 (ashlv2si3_di, WSLLW)
- IWMMXT_BUILTIN2 (ashlv2si3, WSLLWI)
- IWMMXT_BUILTIN2 (ashldi3_di, WSLLD)
- IWMMXT_BUILTIN2 (ashldi3_iwmmxt, WSLLDI)
- IWMMXT_BUILTIN2 (lshrv4hi3_di, WSRLH)
- IWMMXT_BUILTIN2 (lshrv4hi3, WSRLHI)
- IWMMXT_BUILTIN2 (lshrv2si3_di, WSRLW)
- IWMMXT_BUILTIN2 (lshrv2si3, WSRLWI)
- IWMMXT_BUILTIN2 (lshrdi3_di, WSRLD)
- IWMMXT_BUILTIN2 (lshrdi3_iwmmxt, WSRLDI)
- IWMMXT_BUILTIN2 (ashrv4hi3_di, WSRAH)
- IWMMXT_BUILTIN2 (ashrv4hi3, WSRAHI)
- IWMMXT_BUILTIN2 (ashrv2si3_di, WSRAW)
- IWMMXT_BUILTIN2 (ashrv2si3, WSRAWI)
- IWMMXT_BUILTIN2 (ashrdi3_di, WSRAD)
- IWMMXT_BUILTIN2 (ashrdi3_iwmmxt, WSRADI)
- IWMMXT_BUILTIN2 (rorv4hi3_di, WRORH)
- IWMMXT_BUILTIN2 (rorv4hi3, WRORHI)
- IWMMXT_BUILTIN2 (rorv2si3_di, WRORW)
- IWMMXT_BUILTIN2 (rorv2si3, WRORWI)
- IWMMXT_BUILTIN2 (rordi3_di, WRORD)
- IWMMXT_BUILTIN2 (rordi3, WRORDI)
- IWMMXT_BUILTIN2 (iwmmxt_wmacuz, WMACUZ)
- IWMMXT_BUILTIN2 (iwmmxt_wmacsz, WMACSZ)
-};
-
-static const struct builtin_description bdesc_1arg[] =
-{
- IWMMXT_BUILTIN (iwmmxt_tmovmskb, "tmovmskb", TMOVMSKB)
- IWMMXT_BUILTIN (iwmmxt_tmovmskh, "tmovmskh", TMOVMSKH)
- IWMMXT_BUILTIN (iwmmxt_tmovmskw, "tmovmskw", TMOVMSKW)
- IWMMXT_BUILTIN (iwmmxt_waccb, "waccb", WACCB)
- IWMMXT_BUILTIN (iwmmxt_wacch, "wacch", WACCH)
- IWMMXT_BUILTIN (iwmmxt_waccw, "waccw", WACCW)
- IWMMXT_BUILTIN (iwmmxt_wunpckehub, "wunpckehub", WUNPCKEHUB)
- IWMMXT_BUILTIN (iwmmxt_wunpckehuh, "wunpckehuh", WUNPCKEHUH)
- IWMMXT_BUILTIN (iwmmxt_wunpckehuw, "wunpckehuw", WUNPCKEHUW)
- IWMMXT_BUILTIN (iwmmxt_wunpckehsb, "wunpckehsb", WUNPCKEHSB)
- IWMMXT_BUILTIN (iwmmxt_wunpckehsh, "wunpckehsh", WUNPCKEHSH)
- IWMMXT_BUILTIN (iwmmxt_wunpckehsw, "wunpckehsw", WUNPCKEHSW)
- IWMMXT_BUILTIN (iwmmxt_wunpckelub, "wunpckelub", WUNPCKELUB)
- IWMMXT_BUILTIN (iwmmxt_wunpckeluh, "wunpckeluh", WUNPCKELUH)
- IWMMXT_BUILTIN (iwmmxt_wunpckeluw, "wunpckeluw", WUNPCKELUW)
- IWMMXT_BUILTIN (iwmmxt_wunpckelsb, "wunpckelsb", WUNPCKELSB)
- IWMMXT_BUILTIN (iwmmxt_wunpckelsh, "wunpckelsh", WUNPCKELSH)
- IWMMXT_BUILTIN (iwmmxt_wunpckelsw, "wunpckelsw", WUNPCKELSW)
-};
-
-/* Set up all the iWMMXt builtins. This is
- not called if TARGET_IWMMXT is zero. */
-
-static void
-arm_init_iwmmxt_builtins (void)
-{
- const struct builtin_description * d;
- size_t i;
- tree endlink = void_list_node;
-
- tree V2SI_type_node = build_vector_type_for_mode (intSI_type_node, V2SImode);
- tree V4HI_type_node = build_vector_type_for_mode (intHI_type_node, V4HImode);
- tree V8QI_type_node = build_vector_type_for_mode (intQI_type_node, V8QImode);
-
- tree int_ftype_int
- = build_function_type (integer_type_node,
- tree_cons (NULL_TREE, integer_type_node, endlink));
- tree v8qi_ftype_v8qi_v8qi_int
- = build_function_type (V8QI_type_node,
- tree_cons (NULL_TREE, V8QI_type_node,
- tree_cons (NULL_TREE, V8QI_type_node,
- tree_cons (NULL_TREE,
- integer_type_node,
- endlink))));
- tree v4hi_ftype_v4hi_int
- = build_function_type (V4HI_type_node,
- tree_cons (NULL_TREE, V4HI_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- endlink)));
- tree v2si_ftype_v2si_int
- = build_function_type (V2SI_type_node,
- tree_cons (NULL_TREE, V2SI_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- endlink)));
- tree v2si_ftype_di_di
- = build_function_type (V2SI_type_node,
- tree_cons (NULL_TREE, long_long_integer_type_node,
- tree_cons (NULL_TREE, long_long_integer_type_node,
- endlink)));
- tree di_ftype_di_int
- = build_function_type (long_long_integer_type_node,
- tree_cons (NULL_TREE, long_long_integer_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- endlink)));
- tree di_ftype_di_int_int
- = build_function_type (long_long_integer_type_node,
- tree_cons (NULL_TREE, long_long_integer_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- tree_cons (NULL_TREE,
- integer_type_node,
- endlink))));
- tree int_ftype_v8qi
- = build_function_type (integer_type_node,
- tree_cons (NULL_TREE, V8QI_type_node,
- endlink));
- tree int_ftype_v4hi
- = build_function_type (integer_type_node,
- tree_cons (NULL_TREE, V4HI_type_node,
- endlink));
- tree int_ftype_v2si
- = build_function_type (integer_type_node,
- tree_cons (NULL_TREE, V2SI_type_node,
- endlink));
- tree int_ftype_v8qi_int
- = build_function_type (integer_type_node,
- tree_cons (NULL_TREE, V8QI_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- endlink)));
- tree int_ftype_v4hi_int
- = build_function_type (integer_type_node,
- tree_cons (NULL_TREE, V4HI_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- endlink)));
- tree int_ftype_v2si_int
- = build_function_type (integer_type_node,
- tree_cons (NULL_TREE, V2SI_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- endlink)));
- tree v8qi_ftype_v8qi_int_int
- = build_function_type (V8QI_type_node,
- tree_cons (NULL_TREE, V8QI_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- tree_cons (NULL_TREE,
- integer_type_node,
- endlink))));
- tree v4hi_ftype_v4hi_int_int
- = build_function_type (V4HI_type_node,
- tree_cons (NULL_TREE, V4HI_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- tree_cons (NULL_TREE,
- integer_type_node,
- endlink))));
- tree v2si_ftype_v2si_int_int
- = build_function_type (V2SI_type_node,
- tree_cons (NULL_TREE, V2SI_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- tree_cons (NULL_TREE,
- integer_type_node,
- endlink))));
- /* Miscellaneous. */
- tree v8qi_ftype_v4hi_v4hi
- = build_function_type (V8QI_type_node,
- tree_cons (NULL_TREE, V4HI_type_node,
- tree_cons (NULL_TREE, V4HI_type_node,
- endlink)));
- tree v4hi_ftype_v2si_v2si
- = build_function_type (V4HI_type_node,
- tree_cons (NULL_TREE, V2SI_type_node,
- tree_cons (NULL_TREE, V2SI_type_node,
- endlink)));
- tree v2si_ftype_v4hi_v4hi
- = build_function_type (V2SI_type_node,
- tree_cons (NULL_TREE, V4HI_type_node,
- tree_cons (NULL_TREE, V4HI_type_node,
- endlink)));
- tree v2si_ftype_v8qi_v8qi
- = build_function_type (V2SI_type_node,
- tree_cons (NULL_TREE, V8QI_type_node,
- tree_cons (NULL_TREE, V8QI_type_node,
- endlink)));
- tree v4hi_ftype_v4hi_di
- = build_function_type (V4HI_type_node,
- tree_cons (NULL_TREE, V4HI_type_node,
- tree_cons (NULL_TREE,
- long_long_integer_type_node,
- endlink)));
- tree v2si_ftype_v2si_di
- = build_function_type (V2SI_type_node,
- tree_cons (NULL_TREE, V2SI_type_node,
- tree_cons (NULL_TREE,
- long_long_integer_type_node,
- endlink)));
- tree void_ftype_int_int
- = build_function_type (void_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- endlink)));
- tree di_ftype_void
- = build_function_type (long_long_unsigned_type_node, endlink);
- tree di_ftype_v8qi
- = build_function_type (long_long_integer_type_node,
- tree_cons (NULL_TREE, V8QI_type_node,
- endlink));
- tree di_ftype_v4hi
- = build_function_type (long_long_integer_type_node,
- tree_cons (NULL_TREE, V4HI_type_node,
- endlink));
- tree di_ftype_v2si
- = build_function_type (long_long_integer_type_node,
- tree_cons (NULL_TREE, V2SI_type_node,
- endlink));
- tree v2si_ftype_v4hi
- = build_function_type (V2SI_type_node,
- tree_cons (NULL_TREE, V4HI_type_node,
- endlink));
- tree v4hi_ftype_v8qi
- = build_function_type (V4HI_type_node,
- tree_cons (NULL_TREE, V8QI_type_node,
- endlink));
-
- tree di_ftype_di_v4hi_v4hi
- = build_function_type (long_long_unsigned_type_node,
- tree_cons (NULL_TREE,
- long_long_unsigned_type_node,
- tree_cons (NULL_TREE, V4HI_type_node,
- tree_cons (NULL_TREE,
- V4HI_type_node,
- endlink))));
-
- tree di_ftype_v4hi_v4hi
- = build_function_type (long_long_unsigned_type_node,
- tree_cons (NULL_TREE, V4HI_type_node,
- tree_cons (NULL_TREE, V4HI_type_node,
- endlink)));
-
- /* Normal vector binops. */
- tree v8qi_ftype_v8qi_v8qi
- = build_function_type (V8QI_type_node,
- tree_cons (NULL_TREE, V8QI_type_node,
- tree_cons (NULL_TREE, V8QI_type_node,
- endlink)));
- tree v4hi_ftype_v4hi_v4hi
- = build_function_type (V4HI_type_node,
- tree_cons (NULL_TREE, V4HI_type_node,
- tree_cons (NULL_TREE, V4HI_type_node,
- endlink)));
- tree v2si_ftype_v2si_v2si
- = build_function_type (V2SI_type_node,
- tree_cons (NULL_TREE, V2SI_type_node,
- tree_cons (NULL_TREE, V2SI_type_node,
- endlink)));
- tree di_ftype_di_di
- = build_function_type (long_long_unsigned_type_node,
- tree_cons (NULL_TREE, long_long_unsigned_type_node,
- tree_cons (NULL_TREE,
- long_long_unsigned_type_node,
- endlink)));
-
- /* Add all builtins that are more or less simple operations on two
- operands. */
- for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
- {
- /* Use one of the operands; the target can have a different mode for
- mask-generating compares. */
- enum machine_mode mode;
- tree type;
-
- if (d->name == 0)
- continue;
-
- mode = insn_data[d->icode].operand[1].mode;
-
- switch (mode)
- {
- case V8QImode:
- type = v8qi_ftype_v8qi_v8qi;
- break;
- case V4HImode:
- type = v4hi_ftype_v4hi_v4hi;
- break;
- case V2SImode:
- type = v2si_ftype_v2si_v2si;
- break;
- case DImode:
- type = di_ftype_di_di;
- break;
-
- default:
- gcc_unreachable ();
- }
-
- def_mbuiltin (d->mask, d->name, type, d->code);
- }
-
- /* Add the remaining MMX insns with somewhat more complicated types. */
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wzero", di_ftype_void, ARM_BUILTIN_WZERO);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_setwcx", void_ftype_int_int, ARM_BUILTIN_SETWCX);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_getwcx", int_ftype_int, ARM_BUILTIN_GETWCX);
-
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsllh", v4hi_ftype_v4hi_di, ARM_BUILTIN_WSLLH);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsllw", v2si_ftype_v2si_di, ARM_BUILTIN_WSLLW);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wslld", di_ftype_di_di, ARM_BUILTIN_WSLLD);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsllhi", v4hi_ftype_v4hi_int, ARM_BUILTIN_WSLLHI);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsllwi", v2si_ftype_v2si_int, ARM_BUILTIN_WSLLWI);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wslldi", di_ftype_di_int, ARM_BUILTIN_WSLLDI);
-
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsrlh", v4hi_ftype_v4hi_di, ARM_BUILTIN_WSRLH);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsrlw", v2si_ftype_v2si_di, ARM_BUILTIN_WSRLW);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsrld", di_ftype_di_di, ARM_BUILTIN_WSRLD);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsrlhi", v4hi_ftype_v4hi_int, ARM_BUILTIN_WSRLHI);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsrlwi", v2si_ftype_v2si_int, ARM_BUILTIN_WSRLWI);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsrldi", di_ftype_di_int, ARM_BUILTIN_WSRLDI);
-
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsrah", v4hi_ftype_v4hi_di, ARM_BUILTIN_WSRAH);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsraw", v2si_ftype_v2si_di, ARM_BUILTIN_WSRAW);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsrad", di_ftype_di_di, ARM_BUILTIN_WSRAD);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsrahi", v4hi_ftype_v4hi_int, ARM_BUILTIN_WSRAHI);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsrawi", v2si_ftype_v2si_int, ARM_BUILTIN_WSRAWI);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsradi", di_ftype_di_int, ARM_BUILTIN_WSRADI);
-
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wrorh", v4hi_ftype_v4hi_di, ARM_BUILTIN_WRORH);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wrorw", v2si_ftype_v2si_di, ARM_BUILTIN_WRORW);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wrord", di_ftype_di_di, ARM_BUILTIN_WRORD);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wrorhi", v4hi_ftype_v4hi_int, ARM_BUILTIN_WRORHI);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wrorwi", v2si_ftype_v2si_int, ARM_BUILTIN_WRORWI);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wrordi", di_ftype_di_int, ARM_BUILTIN_WRORDI);
-
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wshufh", v4hi_ftype_v4hi_int, ARM_BUILTIN_WSHUFH);
-
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsadb", v2si_ftype_v8qi_v8qi, ARM_BUILTIN_WSADB);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsadh", v2si_ftype_v4hi_v4hi, ARM_BUILTIN_WSADH);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsadbz", v2si_ftype_v8qi_v8qi, ARM_BUILTIN_WSADBZ);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsadhz", v2si_ftype_v4hi_v4hi, ARM_BUILTIN_WSADHZ);
-
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_textrmsb", int_ftype_v8qi_int, ARM_BUILTIN_TEXTRMSB);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_textrmsh", int_ftype_v4hi_int, ARM_BUILTIN_TEXTRMSH);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_textrmsw", int_ftype_v2si_int, ARM_BUILTIN_TEXTRMSW);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_textrmub", int_ftype_v8qi_int, ARM_BUILTIN_TEXTRMUB);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_textrmuh", int_ftype_v4hi_int, ARM_BUILTIN_TEXTRMUH);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_textrmuw", int_ftype_v2si_int, ARM_BUILTIN_TEXTRMUW);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_tinsrb", v8qi_ftype_v8qi_int_int, ARM_BUILTIN_TINSRB);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_tinsrh", v4hi_ftype_v4hi_int_int, ARM_BUILTIN_TINSRH);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_tinsrw", v2si_ftype_v2si_int_int, ARM_BUILTIN_TINSRW);
-
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_waccb", di_ftype_v8qi, ARM_BUILTIN_WACCB);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wacch", di_ftype_v4hi, ARM_BUILTIN_WACCH);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_waccw", di_ftype_v2si, ARM_BUILTIN_WACCW);
-
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_tmovmskb", int_ftype_v8qi, ARM_BUILTIN_TMOVMSKB);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_tmovmskh", int_ftype_v4hi, ARM_BUILTIN_TMOVMSKH);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_tmovmskw", int_ftype_v2si, ARM_BUILTIN_TMOVMSKW);
-
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wpackhss", v8qi_ftype_v4hi_v4hi, ARM_BUILTIN_WPACKHSS);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wpackhus", v8qi_ftype_v4hi_v4hi, ARM_BUILTIN_WPACKHUS);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wpackwus", v4hi_ftype_v2si_v2si, ARM_BUILTIN_WPACKWUS);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wpackwss", v4hi_ftype_v2si_v2si, ARM_BUILTIN_WPACKWSS);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wpackdus", v2si_ftype_di_di, ARM_BUILTIN_WPACKDUS);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wpackdss", v2si_ftype_di_di, ARM_BUILTIN_WPACKDSS);
-
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wunpckehub", v4hi_ftype_v8qi, ARM_BUILTIN_WUNPCKEHUB);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wunpckehuh", v2si_ftype_v4hi, ARM_BUILTIN_WUNPCKEHUH);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wunpckehuw", di_ftype_v2si, ARM_BUILTIN_WUNPCKEHUW);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wunpckehsb", v4hi_ftype_v8qi, ARM_BUILTIN_WUNPCKEHSB);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wunpckehsh", v2si_ftype_v4hi, ARM_BUILTIN_WUNPCKEHSH);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wunpckehsw", di_ftype_v2si, ARM_BUILTIN_WUNPCKEHSW);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wunpckelub", v4hi_ftype_v8qi, ARM_BUILTIN_WUNPCKELUB);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wunpckeluh", v2si_ftype_v4hi, ARM_BUILTIN_WUNPCKELUH);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wunpckeluw", di_ftype_v2si, ARM_BUILTIN_WUNPCKELUW);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wunpckelsb", v4hi_ftype_v8qi, ARM_BUILTIN_WUNPCKELSB);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wunpckelsh", v2si_ftype_v4hi, ARM_BUILTIN_WUNPCKELSH);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wunpckelsw", di_ftype_v2si, ARM_BUILTIN_WUNPCKELSW);
-
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wmacs", di_ftype_di_v4hi_v4hi, ARM_BUILTIN_WMACS);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wmacsz", di_ftype_v4hi_v4hi, ARM_BUILTIN_WMACSZ);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wmacu", di_ftype_di_v4hi_v4hi, ARM_BUILTIN_WMACU);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_wmacuz", di_ftype_v4hi_v4hi, ARM_BUILTIN_WMACUZ);
-
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_walign", v8qi_ftype_v8qi_v8qi_int, ARM_BUILTIN_WALIGN);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_tmia", di_ftype_di_int_int, ARM_BUILTIN_TMIA);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_tmiaph", di_ftype_di_int_int, ARM_BUILTIN_TMIAPH);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_tmiabb", di_ftype_di_int_int, ARM_BUILTIN_TMIABB);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_tmiabt", di_ftype_di_int_int, ARM_BUILTIN_TMIABT);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_tmiatb", di_ftype_di_int_int, ARM_BUILTIN_TMIATB);
- def_mbuiltin (FL_IWMMXT, "__builtin_arm_tmiatt", di_ftype_di_int_int, ARM_BUILTIN_TMIATT);
-}
-
-static void
-arm_init_tls_builtins (void)
-{
- tree ftype;
- tree nothrow = tree_cons (get_identifier ("nothrow"), NULL, NULL);
- tree const_nothrow = tree_cons (get_identifier ("const"), NULL, nothrow);
-
- ftype = build_function_type (ptr_type_node, void_list_node);
- lang_hooks.builtin_function ("__builtin_thread_pointer", ftype,
- ARM_BUILTIN_THREAD_POINTER, BUILT_IN_MD,
- NULL, const_nothrow);
-}
-
-static void
-arm_init_builtins (void)
-{
- arm_init_tls_builtins ();
-
- if (TARGET_REALLY_IWMMXT)
- arm_init_iwmmxt_builtins ();
-}
-
-/* Errors in the source file can cause expand_expr to return const0_rtx
- where we expect a vector. To avoid crashing, use one of the vector
- clear instructions. */
-
-static rtx
-safe_vector_operand (rtx x, enum machine_mode mode)
-{
- if (x != const0_rtx)
- return x;
- x = gen_reg_rtx (mode);
-
- emit_insn (gen_iwmmxt_clrdi (mode == DImode ? x
- : gen_rtx_SUBREG (DImode, x, 0)));
- return x;
-}
-
-/* Subroutine of arm_expand_builtin to take care of binop insns. */
-
-static rtx
-arm_expand_binop_builtin (enum insn_code icode,
- tree arglist, rtx target)
-{
- rtx pat;
- tree arg0 = TREE_VALUE (arglist);
- tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- rtx op0 = expand_normal (arg0);
- rtx op1 = expand_normal (arg1);
- enum machine_mode tmode = insn_data[icode].operand[0].mode;
- enum machine_mode mode0 = insn_data[icode].operand[1].mode;
- enum machine_mode mode1 = insn_data[icode].operand[2].mode;
-
- if (VECTOR_MODE_P (mode0))
- op0 = safe_vector_operand (op0, mode0);
- if (VECTOR_MODE_P (mode1))
- op1 = safe_vector_operand (op1, mode1);
-
- if (! target
- || GET_MODE (target) != tmode
- || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
- target = gen_reg_rtx (tmode);
-
- gcc_assert (GET_MODE (op0) == mode0 && GET_MODE (op1) == mode1);
-
- if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
- op0 = copy_to_mode_reg (mode0, op0);
- if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
- op1 = copy_to_mode_reg (mode1, op1);
-
- pat = GEN_FCN (icode) (target, op0, op1);
- if (! pat)
- return 0;
- emit_insn (pat);
- return target;
-}
-
-/* Subroutine of arm_expand_builtin to take care of unop insns. */
-
-static rtx
-arm_expand_unop_builtin (enum insn_code icode,
- tree arglist, rtx target, int do_load)
-{
- rtx pat;
- tree arg0 = TREE_VALUE (arglist);
- rtx op0 = expand_normal (arg0);
- enum machine_mode tmode = insn_data[icode].operand[0].mode;
- enum machine_mode mode0 = insn_data[icode].operand[1].mode;
-
- if (! target
- || GET_MODE (target) != tmode
- || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
- target = gen_reg_rtx (tmode);
- if (do_load)
- op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
- else
- {
- if (VECTOR_MODE_P (mode0))
- op0 = safe_vector_operand (op0, mode0);
-
- if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
- op0 = copy_to_mode_reg (mode0, op0);
- }
-
- pat = GEN_FCN (icode) (target, op0);
- if (! pat)
- return 0;
- emit_insn (pat);
- return target;
-}
-
-/* Expand an expression EXP that calls a built-in function,
- with result going to TARGET if that's convenient
- (and in mode MODE if that's convenient).
- SUBTARGET may be used as the target for computing one of EXP's operands.
- IGNORE is nonzero if the value is to be ignored. */
-
-static rtx
-arm_expand_builtin (tree exp,
- rtx target,
- rtx subtarget ATTRIBUTE_UNUSED,
- enum machine_mode mode ATTRIBUTE_UNUSED,
- int ignore ATTRIBUTE_UNUSED)
-{
- const struct builtin_description * d;
- enum insn_code icode;
- tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
- tree arglist = TREE_OPERAND (exp, 1);
- tree arg0;
- tree arg1;
- tree arg2;
- rtx op0;
- rtx op1;
- rtx op2;
- rtx pat;
- int fcode = DECL_FUNCTION_CODE (fndecl);
- size_t i;
- enum machine_mode tmode;
- enum machine_mode mode0;
- enum machine_mode mode1;
- enum machine_mode mode2;
-
- switch (fcode)
- {
- case ARM_BUILTIN_TEXTRMSB:
- case ARM_BUILTIN_TEXTRMUB:
- case ARM_BUILTIN_TEXTRMSH:
- case ARM_BUILTIN_TEXTRMUH:
- case ARM_BUILTIN_TEXTRMSW:
- case ARM_BUILTIN_TEXTRMUW:
- icode = (fcode == ARM_BUILTIN_TEXTRMSB ? CODE_FOR_iwmmxt_textrmsb
- : fcode == ARM_BUILTIN_TEXTRMUB ? CODE_FOR_iwmmxt_textrmub
- : fcode == ARM_BUILTIN_TEXTRMSH ? CODE_FOR_iwmmxt_textrmsh
- : fcode == ARM_BUILTIN_TEXTRMUH ? CODE_FOR_iwmmxt_textrmuh
- : CODE_FOR_iwmmxt_textrmw);
-
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- op0 = expand_normal (arg0);
- op1 = expand_normal (arg1);
- tmode = insn_data[icode].operand[0].mode;
- mode0 = insn_data[icode].operand[1].mode;
- mode1 = insn_data[icode].operand[2].mode;
-
- if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
- op0 = copy_to_mode_reg (mode0, op0);
- if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
- {
- /* @@@ better error message */
- error ("selector must be an immediate");
- return gen_reg_rtx (tmode);
- }
- if (target == 0
- || GET_MODE (target) != tmode
- || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
- target = gen_reg_rtx (tmode);
- pat = GEN_FCN (icode) (target, op0, op1);
- if (! pat)
- return 0;
- emit_insn (pat);
- return target;
-
- case ARM_BUILTIN_TINSRB:
- case ARM_BUILTIN_TINSRH:
- case ARM_BUILTIN_TINSRW:
- icode = (fcode == ARM_BUILTIN_TINSRB ? CODE_FOR_iwmmxt_tinsrb
- : fcode == ARM_BUILTIN_TINSRH ? CODE_FOR_iwmmxt_tinsrh
- : CODE_FOR_iwmmxt_tinsrw);
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- op0 = expand_normal (arg0);
- op1 = expand_normal (arg1);
- op2 = expand_normal (arg2);
- tmode = insn_data[icode].operand[0].mode;
- mode0 = insn_data[icode].operand[1].mode;
- mode1 = insn_data[icode].operand[2].mode;
- mode2 = insn_data[icode].operand[3].mode;
-
- if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
- op0 = copy_to_mode_reg (mode0, op0);
- if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
- op1 = copy_to_mode_reg (mode1, op1);
- if (! (*insn_data[icode].operand[3].predicate) (op2, mode2))
- {
- /* @@@ better error message */
- error ("selector must be an immediate");
- return const0_rtx;
- }
- if (target == 0
- || GET_MODE (target) != tmode
- || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
- target = gen_reg_rtx (tmode);
- pat = GEN_FCN (icode) (target, op0, op1, op2);
- if (! pat)
- return 0;
- emit_insn (pat);
- return target;
-
- case ARM_BUILTIN_SETWCX:
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- op0 = force_reg (SImode, expand_normal (arg0));
- op1 = expand_normal (arg1);
- emit_insn (gen_iwmmxt_tmcr (op1, op0));
- return 0;
-
- case ARM_BUILTIN_GETWCX:
- arg0 = TREE_VALUE (arglist);
- op0 = expand_normal (arg0);
- target = gen_reg_rtx (SImode);
- emit_insn (gen_iwmmxt_tmrc (target, op0));
- return target;
-
- case ARM_BUILTIN_WSHUFH:
- icode = CODE_FOR_iwmmxt_wshufh;
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- op0 = expand_normal (arg0);
- op1 = expand_normal (arg1);
- tmode = insn_data[icode].operand[0].mode;
- mode1 = insn_data[icode].operand[1].mode;
- mode2 = insn_data[icode].operand[2].mode;
-
- if (! (*insn_data[icode].operand[1].predicate) (op0, mode1))
- op0 = copy_to_mode_reg (mode1, op0);
- if (! (*insn_data[icode].operand[2].predicate) (op1, mode2))
- {
- /* @@@ better error message */
- error ("mask must be an immediate");
- return const0_rtx;
- }
- if (target == 0
- || GET_MODE (target) != tmode
- || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
- target = gen_reg_rtx (tmode);
- pat = GEN_FCN (icode) (target, op0, op1);
- if (! pat)
- return 0;
- emit_insn (pat);
- return target;
-
- case ARM_BUILTIN_WSADB:
- return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wsadb, arglist, target);
- case ARM_BUILTIN_WSADH:
- return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wsadh, arglist, target);
- case ARM_BUILTIN_WSADBZ:
- return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wsadbz, arglist, target);
- case ARM_BUILTIN_WSADHZ:
- return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wsadhz, arglist, target);
-
- /* Several three-argument builtins. */
- case ARM_BUILTIN_WMACS:
- case ARM_BUILTIN_WMACU:
- case ARM_BUILTIN_WALIGN:
- case ARM_BUILTIN_TMIA:
- case ARM_BUILTIN_TMIAPH:
- case ARM_BUILTIN_TMIATT:
- case ARM_BUILTIN_TMIATB:
- case ARM_BUILTIN_TMIABT:
- case ARM_BUILTIN_TMIABB:
- icode = (fcode == ARM_BUILTIN_WMACS ? CODE_FOR_iwmmxt_wmacs
- : fcode == ARM_BUILTIN_WMACU ? CODE_FOR_iwmmxt_wmacu
- : fcode == ARM_BUILTIN_TMIA ? CODE_FOR_iwmmxt_tmia
- : fcode == ARM_BUILTIN_TMIAPH ? CODE_FOR_iwmmxt_tmiaph
- : fcode == ARM_BUILTIN_TMIABB ? CODE_FOR_iwmmxt_tmiabb
- : fcode == ARM_BUILTIN_TMIABT ? CODE_FOR_iwmmxt_tmiabt
- : fcode == ARM_BUILTIN_TMIATB ? CODE_FOR_iwmmxt_tmiatb
- : fcode == ARM_BUILTIN_TMIATT ? CODE_FOR_iwmmxt_tmiatt
- : CODE_FOR_iwmmxt_walign);
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- op0 = expand_normal (arg0);
- op1 = expand_normal (arg1);
- op2 = expand_normal (arg2);
- tmode = insn_data[icode].operand[0].mode;
- mode0 = insn_data[icode].operand[1].mode;
- mode1 = insn_data[icode].operand[2].mode;
- mode2 = insn_data[icode].operand[3].mode;
-
- if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
- op0 = copy_to_mode_reg (mode0, op0);
- if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
- op1 = copy_to_mode_reg (mode1, op1);
- if (! (*insn_data[icode].operand[3].predicate) (op2, mode2))
- op2 = copy_to_mode_reg (mode2, op2);
- if (target == 0
- || GET_MODE (target) != tmode
- || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
- target = gen_reg_rtx (tmode);
- pat = GEN_FCN (icode) (target, op0, op1, op2);
- if (! pat)
- return 0;
- emit_insn (pat);
- return target;
-
- case ARM_BUILTIN_WZERO:
- target = gen_reg_rtx (DImode);
- emit_insn (gen_iwmmxt_clrdi (target));
- return target;
-
- case ARM_BUILTIN_THREAD_POINTER:
- return arm_load_tp (target);
-
- default:
- break;
- }
-
- for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
- if (d->code == (const enum arm_builtins) fcode)
- return arm_expand_binop_builtin (d->icode, arglist, target);
-
- for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
- if (d->code == (const enum arm_builtins) fcode)
- return arm_expand_unop_builtin (d->icode, arglist, target, 0);
-
- /* @@@ Should really do something sensible here. */
- return NULL_RTX;
-}
-
-/* Return the number (counting from 0) of
- the least significant set bit in MASK. */
-
-inline static int
-number_of_first_bit_set (unsigned mask)
-{
- int bit;
-
- for (bit = 0;
- (mask & (1 << bit)) == 0;
- ++bit)
- continue;
-
- return bit;
-}
-
-/* Emit code to push or pop registers to or from the stack. F is the
- assembly file. MASK is the registers to push or pop. PUSH is
- nonzero if we should push, and zero if we should pop. For debugging
- output, if pushing, adjust CFA_OFFSET by the amount of space added
- to the stack. REAL_REGS should have the same number of bits set as
- MASK, and will be used instead (in the same order) to describe which
- registers were saved - this is used to mark the save slots when we
- push high registers after moving them to low registers. */
-static void
-thumb_pushpop (FILE *f, unsigned long mask, int push, int *cfa_offset,
- unsigned long real_regs)
-{
- int regno;
- int lo_mask = mask & 0xFF;
- int pushed_words = 0;
-
- gcc_assert (mask);
-
- if (lo_mask == 0 && !push && (mask & (1 << PC_REGNUM)))
- {
- /* Special case. Do not generate a POP PC statement here, do it in
- thumb_exit() */
- thumb_exit (f, -1);
- return;
- }
-
- if (ARM_EABI_UNWIND_TABLES && push)
- {
- fprintf (f, "\t.save\t{");
- for (regno = 0; regno < 15; regno++)
- {
- if (real_regs & (1 << regno))
- {
- if (real_regs & ((1 << regno) -1))
- fprintf (f, ", ");
- asm_fprintf (f, "%r", regno);
- }
- }
- fprintf (f, "}\n");
- }
-
- fprintf (f, "\t%s\t{", push ? "push" : "pop");
-
- /* Look at the low registers first. */
- for (regno = 0; regno <= LAST_LO_REGNUM; regno++, lo_mask >>= 1)
- {
- if (lo_mask & 1)
- {
- asm_fprintf (f, "%r", regno);
-
- if ((lo_mask & ~1) != 0)
- fprintf (f, ", ");
-
- pushed_words++;
- }
- }
-
- if (push && (mask & (1 << LR_REGNUM)))
- {
- /* Catch pushing the LR. */
- if (mask & 0xFF)
- fprintf (f, ", ");
-
- asm_fprintf (f, "%r", LR_REGNUM);
-
- pushed_words++;
- }
- else if (!push && (mask & (1 << PC_REGNUM)))
- {
- /* Catch popping the PC. */
- if (TARGET_INTERWORK || TARGET_BACKTRACE
- || current_function_calls_eh_return)
- {
- /* The PC is never poped directly, instead
- it is popped into r3 and then BX is used. */
- fprintf (f, "}\n");
-
- thumb_exit (f, -1);
-
- return;
- }
- else
- {
- if (mask & 0xFF)
- fprintf (f, ", ");
-
- asm_fprintf (f, "%r", PC_REGNUM);
- }
- }
-
- fprintf (f, "}\n");
-
- if (push && pushed_words && dwarf2out_do_frame ())
- {
- char *l = dwarf2out_cfi_label ();
- int pushed_mask = real_regs;
-
- *cfa_offset += pushed_words * 4;
- dwarf2out_def_cfa (l, SP_REGNUM, *cfa_offset);
-
- pushed_words = 0;
- pushed_mask = real_regs;
- for (regno = 0; regno <= 14; regno++, pushed_mask >>= 1)
- {
- if (pushed_mask & 1)
- dwarf2out_reg_save (l, regno, 4 * pushed_words++ - *cfa_offset);
- }
- }
-}
-
-/* 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)
-{
- unsigned regs_available_for_popping;
- unsigned regs_to_pop;
- int pops_needed;
- unsigned available;
- unsigned required;
- int mode;
- int size;
- int restore_a4 = FALSE;
-
- /* Compute the registers we need to pop. */
- regs_to_pop = 0;
- pops_needed = 0;
-
- if (reg_containing_return_addr == -1)
- {
- regs_to_pop |= 1 << LR_REGNUM;
- ++pops_needed;
- }
-
- if (TARGET_BACKTRACE)
- {
- /* Restore the (ARM) frame pointer and stack pointer. */
- regs_to_pop |= (1 << ARM_HARD_FRAME_POINTER_REGNUM) | (1 << SP_REGNUM);
- pops_needed += 2;
- }
-
- /* If there is nothing to pop then just emit the BX instruction and
- return. */
- if (pops_needed == 0)
- {
- if (current_function_calls_eh_return)
- asm_fprintf (f, "\tadd\t%r, %r\n", SP_REGNUM, ARM_EH_STACKADJ_REGNUM);
-
- asm_fprintf (f, "\tbx\t%r\n", reg_containing_return_addr);
- return;
- }
- /* Otherwise if we are not supporting interworking and we have not created
- a backtrace structure and the function was not entered in ARM mode then
- just pop the return address straight into the PC. */
- else if (!TARGET_INTERWORK
- && !TARGET_BACKTRACE
- && !is_called_in_ARM_mode (current_function_decl)
- && !current_function_calls_eh_return)
- {
- asm_fprintf (f, "\tpop\t{%r}\n", PC_REGNUM);
- return;
- }
-
- /* Find out how many of the (return) argument registers we can corrupt. */
- regs_available_for_popping = 0;
-
- /* If returning via __builtin_eh_return, the bottom three registers
- all contain information needed for the return. */
- if (current_function_calls_eh_return)
- size = 12;
- else
- {
- /* 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)
- regs_available_for_popping =
- (1 << ARG_REGISTER (1))
- | (1 << ARG_REGISTER (2))
- | (1 << ARG_REGISTER (3));
- else
- regs_available_for_popping =
- (1 << ARG_REGISTER (2))
- | (1 << ARG_REGISTER (3));
- }
- else if (size <= 4)
- regs_available_for_popping =
- (1 << ARG_REGISTER (2))
- | (1 << ARG_REGISTER (3));
- else if (size <= 8)
- regs_available_for_popping =
- (1 << ARG_REGISTER (3));
- }
-
- /* Match registers to be popped with registers into which we pop them. */
- for (available = regs_available_for_popping,
- required = regs_to_pop;
- required != 0 && available != 0;
- available &= ~(available & - available),
- required &= ~(required & - required))
- -- pops_needed;
-
- /* If we have any popping registers left over, remove them. */
- if (available > 0)
- regs_available_for_popping &= ~available;
-
- /* Otherwise if we need another popping register we can use
- the fourth argument register. */
- else if (pops_needed)
- {
- /* If we have not found any free argument registers and
- reg a4 contains the return address, we must move it. */
- if (regs_available_for_popping == 0
- && reg_containing_return_addr == LAST_ARG_REGNUM)
- {
- asm_fprintf (f, "\tmov\t%r, %r\n", LR_REGNUM, LAST_ARG_REGNUM);
- reg_containing_return_addr = LR_REGNUM;
- }
- else 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%r, %r\n",IP_REGNUM, LAST_ARG_REGNUM);
- }
-
- if (reg_containing_return_addr != LAST_ARG_REGNUM)
- {
- /* The fourth argument register is available. */
- regs_available_for_popping |= 1 << LAST_ARG_REGNUM;
-
- --pops_needed;
- }
- }
-
- /* Pop as many registers as we can. */
- thumb_pushpop (f, regs_available_for_popping, FALSE, NULL,
- regs_available_for_popping);
-
- /* Process the registers we popped. */
- if (reg_containing_return_addr == -1)
- {
- /* The return address was popped into the lowest numbered register. */
- regs_to_pop &= ~(1 << LR_REGNUM);
-
- reg_containing_return_addr =
- number_of_first_bit_set (regs_available_for_popping);
-
- /* Remove this register for the mask of available registers, so that
- the return address will not be corrupted by further pops. */
- regs_available_for_popping &= ~(1 << reg_containing_return_addr);
- }
-
- /* If we popped other registers then handle them here. */
- if (regs_available_for_popping)
- {
- int frame_pointer;
-
- /* Work out which register currently contains the frame pointer. */
- frame_pointer = number_of_first_bit_set (regs_available_for_popping);
-
- /* Move it into the correct place. */
- asm_fprintf (f, "\tmov\t%r, %r\n",
- ARM_HARD_FRAME_POINTER_REGNUM, frame_pointer);
-
- /* (Temporarily) remove it from the mask of popped registers. */
- regs_available_for_popping &= ~(1 << frame_pointer);
- regs_to_pop &= ~(1 << ARM_HARD_FRAME_POINTER_REGNUM);
-
- if (regs_available_for_popping)
- {
- int stack_pointer;
-
- /* We popped the stack pointer as well,
- find the register that contains it. */
- stack_pointer = number_of_first_bit_set (regs_available_for_popping);
-
- /* Move it into the stack register. */
- asm_fprintf (f, "\tmov\t%r, %r\n", SP_REGNUM, stack_pointer);
-
- /* At this point we have popped all necessary registers, so
- do not worry about restoring regs_available_for_popping
- to its correct value:
-
- assert (pops_needed == 0)
- assert (regs_available_for_popping == (1 << frame_pointer))
- assert (regs_to_pop == (1 << STACK_POINTER)) */
- }
- else
- {
- /* Since we have just move the popped value into the frame
- pointer, the popping register is available for reuse, and
- we know that we still have the stack pointer left to pop. */
- regs_available_for_popping |= (1 << frame_pointer);
- }
- }
-
- /* If we still have registers left on the stack, but we no longer have
- any registers into which we can pop them, then we must move the return
- address into the link register and make available the register that
- contained it. */
- if (regs_available_for_popping == 0 && pops_needed > 0)
- {
- regs_available_for_popping |= 1 << reg_containing_return_addr;
-
- asm_fprintf (f, "\tmov\t%r, %r\n", LR_REGNUM,
- reg_containing_return_addr);
-
- reg_containing_return_addr = LR_REGNUM;
- }
-
- /* If we have registers left on the stack then pop some more.
- We know that at most we will want to pop FP and SP. */
- if (pops_needed > 0)
- {
- int popped_into;
- int move_to;
-
- thumb_pushpop (f, regs_available_for_popping, FALSE, NULL,
- regs_available_for_popping);
-
- /* We have popped either FP or SP.
- Move whichever one it is into the correct register. */
- popped_into = number_of_first_bit_set (regs_available_for_popping);
- move_to = number_of_first_bit_set (regs_to_pop);
-
- asm_fprintf (f, "\tmov\t%r, %r\n", move_to, popped_into);
-
- regs_to_pop &= ~(1 << move_to);
-
- --pops_needed;
- }
-
- /* If we still have not popped everything then we must have only
- had one register available to us and we are now popping the SP. */
- if (pops_needed > 0)
- {
- int popped_into;
-
- thumb_pushpop (f, regs_available_for_popping, FALSE, NULL,
- regs_available_for_popping);
-
- popped_into = number_of_first_bit_set (regs_available_for_popping);
-
- asm_fprintf (f, "\tmov\t%r, %r\n", SP_REGNUM, popped_into);
- /*
- assert (regs_to_pop == (1 << STACK_POINTER))
- assert (pops_needed == 1)
- */
- }
-
- /* If necessary restore the a4 register. */
- if (restore_a4)
- {
- if (reg_containing_return_addr != LR_REGNUM)
- {
- asm_fprintf (f, "\tmov\t%r, %r\n", LR_REGNUM, LAST_ARG_REGNUM);
- reg_containing_return_addr = LR_REGNUM;
- }
-
- asm_fprintf (f, "\tmov\t%r, %r\n", LAST_ARG_REGNUM, IP_REGNUM);
- }
-
- if (current_function_calls_eh_return)
- asm_fprintf (f, "\tadd\t%r, %r\n", SP_REGNUM, ARM_EH_STACKADJ_REGNUM);
-
- /* Return to caller. */
- asm_fprintf (f, "\tbx\t%r\n", reg_containing_return_addr);
-}
-
-
-void
-thumb_final_prescan_insn (rtx insn)
-{
- if (flag_print_asm_name)
- asm_fprintf (asm_out_file, "%@ 0x%04x\n",
- INSN_ADDRESSES (INSN_UID (insn)));
-}
-
-int
-thumb_shiftable_const (unsigned HOST_WIDE_INT val)
-{
- unsigned HOST_WIDE_INT mask = 0xff;
- int i;
-
- if (val == 0) /* XXX */
- return 0;
-
- for (i = 0; i < 25; i++)
- if ((val & (mask << i)) == val)
- return 1;
-
- return 0;
-}
-
-/* Returns nonzero if the current function contains,
- or might contain a far jump. */
-static int
-thumb_far_jump_used_p (void)
-{
- rtx insn;
-
- /* This test is only important for leaf functions. */
- /* assert (!leaf_function_p ()); */
-
- /* If we have already decided that far jumps may be used,
- do not bother checking again, and always return true even if
- it turns out that they are not being used. Once we have made
- the decision that far jumps are present (and that hence the link
- register will be pushed onto the stack) we cannot go back on it. */
- if (cfun->machine->far_jump_used)
- return 1;
-
- /* If this function is not being called from the prologue/epilogue
- generation code then it must be being called from the
- INITIAL_ELIMINATION_OFFSET macro. */
- if (!(ARM_DOUBLEWORD_ALIGN || reload_completed))
- {
- /* In this case we know that we are being asked about the elimination
- of the arg pointer register. If that register is not being used,
- then there are no arguments on the stack, and we do not have to
- worry that a far jump might force the prologue to push the link
- register, changing the stack offsets. In this case we can just
- return false, since the presence of far jumps in the function will
- not affect stack offsets.
-
- If the arg pointer is live (or if it was live, but has now been
- eliminated and so set to dead) then we do have to test to see if
- the function might contain a far jump. This test can lead to some
- false negatives, since before reload is completed, then length of
- branch instructions is not known, so gcc defaults to returning their
- longest length, which in turn sets the far jump attribute to true.
-
- A false negative will not result in bad code being generated, but it
- will result in a needless push and pop of the link register. We
- hope that this does not occur too often.
-
- If we need doubleword stack alignment this could affect the other
- elimination offsets so we can't risk getting it wrong. */
- if (regs_ever_live [ARG_POINTER_REGNUM])
- cfun->machine->arg_pointer_live = 1;
- else if (!cfun->machine->arg_pointer_live)
- return 0;
- }
-
- /* Check to see if the function contains a branch
- insn with the far jump attribute set. */
- 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
- )
- {
- /* Record the fact that we have decided that
- the function does use far jumps. */
- cfun->machine->far_jump_used = 1;
- return 1;
- }
- }
-
- return 0;
-}
-
-/* Return nonzero if FUNC must be entered in ARM mode. */
-int
-is_called_in_ARM_mode (tree func)
-{
- gcc_assert (TREE_CODE (func) == FUNCTION_DECL);
-
- /* Ignore the problem about functions whose address is taken. */
- if (TARGET_CALLEE_INTERWORKING && TREE_PUBLIC (func))
- return TRUE;
-
-#ifdef ARM_PE
- return lookup_attribute ("interfacearm", DECL_ATTRIBUTES (func)) != NULL_TREE;
-#else
- return FALSE;
-#endif
-}
-
-/* The bits which aren't usefully expanded as rtl. */
-const char *
-thumb_unexpanded_epilogue (void)
-{
- int regno;
- unsigned long live_regs_mask = 0;
- int high_regs_pushed = 0;
- int had_to_push_lr;
- int size;
-
- if (return_used_this_function)
- return "";
-
- if (IS_NAKED (arm_current_func_type ()))
- return "";
-
- live_regs_mask = thumb_compute_save_reg_mask ();
- high_regs_pushed = bit_count (live_regs_mask & 0x0f00);
-
- /* 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. */
- size = arm_size_return_regs ();
-
- /* The prolog may have pushed some high registers to use as
- work registers. e.g. the testsuite 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)
- {
- unsigned long mask = live_regs_mask & 0xff;
- int next_hi_reg;
-
- /* The available low registers depend on the size of the value we are
- returning. */
- if (size <= 12)
- mask |= 1 << 3;
- if (size <= 8)
- mask |= 1 << 2;
-
- if (mask == 0)
- /* Oh dear! We have no low registers into which we can pop
- high registers! */
- internal_error
- ("no low registers available for popping high registers");
-
- for (next_hi_reg = 8; next_hi_reg < 13; next_hi_reg++)
- if (live_regs_mask & (1 << next_hi_reg))
- break;
-
- while (high_regs_pushed)
- {
- /* Find lo register(s) into which the high register(s) can
- be popped. */
- for (regno = 0; regno <= LAST_LO_REGNUM; 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, NULL, mask);
-
- /* Move the value(s) into the high registers. */
- for (regno = 0; regno <= LAST_LO_REGNUM; regno++)
- {
- if (mask & (1 << regno))
- {
- asm_fprintf (asm_out_file, "\tmov\t%r, %r\n", next_hi_reg,
- regno);
-
- for (next_hi_reg++; next_hi_reg < 13; next_hi_reg++)
- if (live_regs_mask & (1 << next_hi_reg))
- break;
- }
- }
- }
- live_regs_mask &= ~0x0f00;
- }
-
- had_to_push_lr = (live_regs_mask & (1 << LR_REGNUM)) != 0;
- live_regs_mask &= 0xff;
-
- if (current_function_pretend_args_size == 0 || TARGET_BACKTRACE)
- {
- /* Pop the return address into the PC. */
- if (had_to_push_lr)
- live_regs_mask |= 1 << PC_REGNUM;
-
- /* Either no argument registers were pushed or a backtrace
- structure was created which includes an adjusted stack
- pointer, so just pop everything. */
- if (live_regs_mask)
- thumb_pushpop (asm_out_file, live_regs_mask, FALSE, NULL,
- live_regs_mask);
-
- /* We have either just popped the return address into the
- PC or it is was kept in LR for the entire function. */
- if (!had_to_push_lr)
- thumb_exit (asm_out_file, LR_REGNUM);
- }
- else
- {
- /* Pop everything but the return address. */
- if (live_regs_mask)
- thumb_pushpop (asm_out_file, live_regs_mask, FALSE, NULL,
- live_regs_mask);
-
- if (had_to_push_lr)
- {
- if (size > 12)
- {
- /* We have no free low regs, so save one. */
- asm_fprintf (asm_out_file, "\tmov\t%r, %r\n", IP_REGNUM,
- LAST_ARG_REGNUM);
- }
-
- /* Get the return address into a temporary register. */
- thumb_pushpop (asm_out_file, 1 << LAST_ARG_REGNUM, 0, NULL,
- 1 << LAST_ARG_REGNUM);
-
- if (size > 12)
- {
- /* Move the return address to lr. */
- asm_fprintf (asm_out_file, "\tmov\t%r, %r\n", LR_REGNUM,
- LAST_ARG_REGNUM);
- /* Restore the low register. */
- asm_fprintf (asm_out_file, "\tmov\t%r, %r\n", LAST_ARG_REGNUM,
- IP_REGNUM);
- regno = LR_REGNUM;
- }
- else
- regno = LAST_ARG_REGNUM;
- }
- else
- regno = LR_REGNUM;
-
- /* Remove the argument registers that were pushed onto the stack. */
- asm_fprintf (asm_out_file, "\tadd\t%r, %r, #%d\n",
- SP_REGNUM, SP_REGNUM,
- current_function_pretend_args_size);
-
- thumb_exit (asm_out_file, regno);
- }
-
- return "";
-}
-
-/* Functions to save and restore machine-specific function data. */
-static struct machine_function *
-arm_init_machine_status (void)
-{
- struct machine_function *machine;
- machine = (machine_function *) ggc_alloc_cleared (sizeof (machine_function));
-
-#if ARM_FT_UNKNOWN != 0
- machine->func_type = ARM_FT_UNKNOWN;
-#endif
- return machine;
-}
-
-/* Return an RTX indicating where the return address to the
- calling function can be found. */
-rtx
-arm_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
-{
- if (count != 0)
- return NULL_RTX;
-
- return get_hard_reg_initial_val (Pmode, LR_REGNUM);
-}
-
-/* Do anything needed before RTL is emitted for each function. */
-void
-arm_init_expanders (void)
-{
- /* Arrange to initialize and mark the machine per-function status. */
- init_machine_status = arm_init_machine_status;
-
- /* This is to stop the combine pass optimizing away the alignment
- adjustment of va_arg. */
- /* ??? It is claimed that this should not be necessary. */
- if (cfun)
- mark_reg_pointer (arg_pointer_rtx, PARM_BOUNDARY);
-}
-
-
-/* Like arm_compute_initial_elimination offset. Simpler because there
- isn't an ABI specified frame pointer for Thumb. Instead, we set it
- to point at the base of the local variables after static stack
- space for a function has been allocated. */
-
-HOST_WIDE_INT
-thumb_compute_initial_elimination_offset (unsigned int from, unsigned int to)
-{
- arm_stack_offsets *offsets;
-
- offsets = arm_get_frame_offsets ();
-
- switch (from)
- {
- case ARG_POINTER_REGNUM:
- switch (to)
- {
- case STACK_POINTER_REGNUM:
- return offsets->outgoing_args - offsets->saved_args;
-
- case FRAME_POINTER_REGNUM:
- return offsets->soft_frame - offsets->saved_args;
-
- case ARM_HARD_FRAME_POINTER_REGNUM:
- return offsets->saved_regs - offsets->saved_args;
-
- case THUMB_HARD_FRAME_POINTER_REGNUM:
- return offsets->locals_base - offsets->saved_args;
-
- default:
- gcc_unreachable ();
- }
- break;
-
- case FRAME_POINTER_REGNUM:
- switch (to)
- {
- case STACK_POINTER_REGNUM:
- return offsets->outgoing_args - offsets->soft_frame;
-
- case ARM_HARD_FRAME_POINTER_REGNUM:
- return offsets->saved_regs - offsets->soft_frame;
-
- case THUMB_HARD_FRAME_POINTER_REGNUM:
- return offsets->locals_base - offsets->soft_frame;
-
- default:
- gcc_unreachable ();
- }
- break;
-
- default:
- gcc_unreachable ();
- }
-}
-
-
-/* Generate the rest of a function's prologue. */
-void
-thumb_expand_prologue (void)
-{
- rtx insn, dwarf;
-
- HOST_WIDE_INT amount;
- arm_stack_offsets *offsets;
- unsigned long func_type;
- int regno;
- unsigned long live_regs_mask;
-
- func_type = arm_current_func_type ();
-
- /* Naked functions don't have prologues. */
- if (IS_NAKED (func_type))
- return;
-
- if (IS_INTERRUPT (func_type))
- {
- error ("interrupt Service Routines cannot be coded in Thumb mode");
- return;
- }
-
- live_regs_mask = thumb_compute_save_reg_mask ();
- /* Load the pic register before setting the frame pointer,
- so we can use r7 as a temporary work register. */
- if (flag_pic && arm_pic_register != INVALID_REGNUM)
- arm_load_pic_register (live_regs_mask);
-
- if (!frame_pointer_needed && CALLER_INTERWORKING_SLOT_SIZE > 0)
- emit_move_insn (gen_rtx_REG (Pmode, ARM_HARD_FRAME_POINTER_REGNUM),
- stack_pointer_rtx);
-
- offsets = arm_get_frame_offsets ();
- amount = offsets->outgoing_args - offsets->saved_regs;
- if (amount)
- {
- if (amount < 512)
- {
- insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (- amount)));
- RTX_FRAME_RELATED_P (insn) = 1;
- }
- else
- {
- rtx reg;
-
- /* The stack decrement is too big for an immediate value in a single
- insn. In theory we could issue multiple subtracts, but after
- three of them it becomes more space efficient to place the full
- value in the constant pool and load into a register. (Also the
- ARM debugger really likes to see only one stack decrement per
- function). So instead we look for a scratch register into which
- we can load the decrement, and then we subtract this from the
- stack pointer. Unfortunately on the thumb the only available
- scratch registers are the argument registers, and we cannot use
- these as they may hold arguments to the function. Instead we
- attempt to locate a call preserved register which is used by this
- function. If we can find one, then we know that it will have
- been pushed at the start of the prologue and so we can corrupt
- it now. */
- for (regno = LAST_ARG_REGNUM + 1; regno <= LAST_LO_REGNUM; regno++)
- if (live_regs_mask & (1 << regno)
- && !(frame_pointer_needed
- && (regno == THUMB_HARD_FRAME_POINTER_REGNUM)))
- break;
-
- if (regno > LAST_LO_REGNUM) /* Very unlikely. */
- {
- rtx spare = gen_rtx_REG (SImode, IP_REGNUM);
-
- /* Choose an arbitrary, non-argument low register. */
- reg = gen_rtx_REG (SImode, LAST_LO_REGNUM);
-
- /* Save it by copying it into a high, scratch register. */
- emit_insn (gen_movsi (spare, reg));
- /* Add a USE to stop propagate_one_insn() from barfing. */
- emit_insn (gen_prologue_use (spare));
-
- /* Decrement the stack. */
- emit_insn (gen_movsi (reg, GEN_INT (- amount)));
- insn = emit_insn (gen_addsi3 (stack_pointer_rtx,
- stack_pointer_rtx, reg));
- RTX_FRAME_RELATED_P (insn) = 1;
- dwarf = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
- plus_constant (stack_pointer_rtx,
- -amount));
- RTX_FRAME_RELATED_P (dwarf) = 1;
- REG_NOTES (insn)
- = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
- REG_NOTES (insn));
-
- /* Restore the low register's original value. */
- emit_insn (gen_movsi (reg, spare));
-
- /* Emit a USE of the restored scratch register, so that flow
- analysis will not consider the restore redundant. The
- register won't be used again in this function and isn't
- restored by the epilogue. */
- emit_insn (gen_prologue_use (reg));
- }
- else
- {
- reg = gen_rtx_REG (SImode, regno);
-
- emit_insn (gen_movsi (reg, GEN_INT (- amount)));
-
- insn = emit_insn (gen_addsi3 (stack_pointer_rtx,
- stack_pointer_rtx, reg));
- RTX_FRAME_RELATED_P (insn) = 1;
- dwarf = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
- plus_constant (stack_pointer_rtx,
- -amount));
- RTX_FRAME_RELATED_P (dwarf) = 1;
- REG_NOTES (insn)
- = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
- REG_NOTES (insn));
- }
- }
- }
-
- if (frame_pointer_needed)
- {
- amount = offsets->outgoing_args - offsets->locals_base;
-
- if (amount < 1024)
- insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx,
- stack_pointer_rtx, GEN_INT (amount)));
- else
- {
- emit_insn (gen_movsi (hard_frame_pointer_rtx, GEN_INT (amount)));
- insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx,
- hard_frame_pointer_rtx,
- stack_pointer_rtx));
- dwarf = gen_rtx_SET (VOIDmode, hard_frame_pointer_rtx,
- plus_constant (stack_pointer_rtx, amount));
- RTX_FRAME_RELATED_P (dwarf) = 1;
- REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
- REG_NOTES (insn));
- }
-
- RTX_FRAME_RELATED_P (insn) = 1;
- }
-
- /* If we are profiling, make sure no instructions are scheduled before
- the call to mcount. Similarly if the user has requested no
- scheduling in the prolog. Similarly if we want non-call exceptions
- using the EABI unwinder, to prevent faulting instructions from being
- swapped with a stack adjustment. */
- if (current_function_profile || !TARGET_SCHED_PROLOG
- || (ARM_EABI_UNWIND_TABLES && flag_non_call_exceptions))
- emit_insn (gen_blockage ());
-
- cfun->machine->lr_save_eliminated = !thumb_force_lr_save ();
- if (live_regs_mask & 0xff)
- cfun->machine->lr_save_eliminated = 0;
-
- /* If the link register is being kept alive, with the return address in it,
- then make sure that it does not get reused by the ce2 pass. */
- if (cfun->machine->lr_save_eliminated)
- emit_insn (gen_prologue_use (gen_rtx_REG (SImode, LR_REGNUM)));
-}
-
-
-void
-thumb_expand_epilogue (void)
-{
- HOST_WIDE_INT amount;
- arm_stack_offsets *offsets;
- int regno;
-
- /* Naked functions don't have prologues. */
- if (IS_NAKED (arm_current_func_type ()))
- return;
-
- offsets = arm_get_frame_offsets ();
- amount = offsets->outgoing_args - offsets->saved_regs;
-
- if (frame_pointer_needed)
- {
- emit_insn (gen_movsi (stack_pointer_rtx, hard_frame_pointer_rtx));
- amount = offsets->locals_base - offsets->saved_regs;
- }
-
- gcc_assert (amount >= 0);
- if (amount)
- {
- if (amount < 512)
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (amount)));
- else
- {
- /* r3 is always free in the epilogue. */
- rtx reg = gen_rtx_REG (SImode, LAST_ARG_REGNUM);
-
- emit_insn (gen_movsi (reg, GEN_INT (amount)));
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg));
- }
- }
-
- /* Emit a USE (stack_pointer_rtx), so that
- the stack adjustment will not be deleted. */
- emit_insn (gen_prologue_use (stack_pointer_rtx));
-
- if (current_function_profile || !TARGET_SCHED_PROLOG)
- emit_insn (gen_blockage ());
-
- /* Emit a clobber for each insn that will be restored in the epilogue,
- so that flow2 will get register lifetimes correct. */
- for (regno = 0; regno < 13; regno++)
- if (regs_ever_live[regno] && !call_used_regs[regno])
- emit_insn (gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, regno)));
-
- if (! regs_ever_live[LR_REGNUM])
- emit_insn (gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, LR_REGNUM)));
-}
-
-static void
-thumb_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
-{
- unsigned long live_regs_mask = 0;
- unsigned long l_mask;
- unsigned high_regs_pushed = 0;
- int cfa_offset = 0;
- int regno;
-
- if (IS_NAKED (arm_current_func_type ()))
- return;
-
- if (is_called_in_ARM_mode (current_function_decl))
- {
- const char * name;
-
- gcc_assert (GET_CODE (DECL_RTL (current_function_decl)) == MEM);
- gcc_assert (GET_CODE (XEXP (DECL_RTL (current_function_decl), 0))
- == SYMBOL_REF);
- name = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
-
- /* Generate code sequence to switch us into Thumb mode. */
- /* The .code 32 directive has already been emitted by
- ASM_DECLARE_FUNCTION_NAME. */
- asm_fprintf (f, "\torr\t%r, %r, #1\n", IP_REGNUM, PC_REGNUM);
- asm_fprintf (f, "\tbx\t%r\n", IP_REGNUM);
-
- /* Generate a label, so that the debugger will notice the
- change in instruction sets. This label is also used by
- the assembler to bypass the ARM code when this function
- is called from a Thumb encoded function elsewhere in the
- same file. Hence the definition of STUB_NAME here must
- agree with the definition in gas/config/tc-arm.c. */
-
-#define STUB_NAME ".real_start_of"
-
- fprintf (f, "\t.code\t16\n");
-#ifdef ARM_PE
- if (arm_dllexport_name_p (name))
- name = arm_strip_name_encoding (name);
-#endif
- asm_fprintf (f, "\t.globl %s%U%s\n", STUB_NAME, name);
- fprintf (f, "\t.thumb_func\n");
- asm_fprintf (f, "%s%U%s:\n", STUB_NAME, name);
- }
-
- if (current_function_pretend_args_size)
- {
- /* Output unwind directive for the stack adjustment. */
- if (ARM_EABI_UNWIND_TABLES)
- fprintf (f, "\t.pad #%d\n",
- current_function_pretend_args_size);
-
- if (cfun->machine->uses_anonymous_args)
- {
- int num_pushes;
-
- fprintf (f, "\tpush\t{");
-
- num_pushes = ARM_NUM_INTS (current_function_pretend_args_size);
-
- for (regno = LAST_ARG_REGNUM + 1 - num_pushes;
- regno <= LAST_ARG_REGNUM;
- regno++)
- asm_fprintf (f, "%r%s", regno,
- regno == LAST_ARG_REGNUM ? "" : ", ");
-
- fprintf (f, "}\n");
- }
- else
- asm_fprintf (f, "\tsub\t%r, %r, #%d\n",
- SP_REGNUM, SP_REGNUM,
- current_function_pretend_args_size);
-
- /* We don't need to record the stores for unwinding (would it
- help the debugger any if we did?), but record the change in
- the stack pointer. */
- if (dwarf2out_do_frame ())
- {
- char *l = dwarf2out_cfi_label ();
-
- cfa_offset = cfa_offset + current_function_pretend_args_size;
- dwarf2out_def_cfa (l, SP_REGNUM, cfa_offset);
- }
- }
-
- /* Get the registers we are going to push. */
- live_regs_mask = thumb_compute_save_reg_mask ();
- /* Extract a mask of the ones we can give to the Thumb's push instruction. */
- l_mask = live_regs_mask & 0x40ff;
- /* Then count how many other high registers will need to be pushed. */
- high_regs_pushed = bit_count (live_regs_mask & 0x0f00);
-
- if (TARGET_BACKTRACE)
- {
- unsigned offset;
- unsigned work_register;
-
- /* We have been asked to create a stack backtrace structure.
- The code looks like this:
-
- 0 .align 2
- 0 func:
- 0 sub SP, #16 Reserve space for 4 registers.
- 2 push {R7} Push low registers.
- 4 add R7, SP, #20 Get the stack pointer before the push.
- 6 str R7, [SP, #8] Store the stack pointer (before reserving the space).
- 8 mov R7, PC Get hold of the start of this code plus 12.
- 10 str R7, [SP, #16] Store it.
- 12 mov R7, FP Get hold of the current frame pointer.
- 14 str R7, [SP, #4] Store it.
- 16 mov R7, LR Get hold of the current return address.
- 18 str R7, [SP, #12] Store it.
- 20 add R7, SP, #16 Point at the start of the backtrace structure.
- 22 mov FP, R7 Put this value into the frame pointer. */
-
- work_register = thumb_find_work_register (live_regs_mask);
-
- if (ARM_EABI_UNWIND_TABLES)
- asm_fprintf (f, "\t.pad #16\n");
-
- asm_fprintf
- (f, "\tsub\t%r, %r, #16\t%@ Create stack backtrace structure\n",
- SP_REGNUM, SP_REGNUM);
-
- if (dwarf2out_do_frame ())
- {
- char *l = dwarf2out_cfi_label ();
-
- cfa_offset = cfa_offset + 16;
- dwarf2out_def_cfa (l, SP_REGNUM, cfa_offset);
- }
-
- if (l_mask)
- {
- thumb_pushpop (f, l_mask, 1, &cfa_offset, l_mask);
- offset = bit_count (l_mask) * UNITS_PER_WORD;
- }
- else
- offset = 0;
-
- asm_fprintf (f, "\tadd\t%r, %r, #%d\n", work_register, SP_REGNUM,
- offset + 16 + current_function_pretend_args_size);
-
- asm_fprintf (f, "\tstr\t%r, [%r, #%d]\n", work_register, SP_REGNUM,
- offset + 4);
-
- /* Make sure that the instruction fetching the PC is in the right place
- to calculate "start of backtrace creation code + 12". */
- if (l_mask)
- {
- asm_fprintf (f, "\tmov\t%r, %r\n", work_register, PC_REGNUM);
- asm_fprintf (f, "\tstr\t%r, [%r, #%d]\n", work_register, SP_REGNUM,
- offset + 12);
- asm_fprintf (f, "\tmov\t%r, %r\n", work_register,
- ARM_HARD_FRAME_POINTER_REGNUM);
- asm_fprintf (f, "\tstr\t%r, [%r, #%d]\n", work_register, SP_REGNUM,
- offset);
- }
- else
- {
- asm_fprintf (f, "\tmov\t%r, %r\n", work_register,
- ARM_HARD_FRAME_POINTER_REGNUM);
- asm_fprintf (f, "\tstr\t%r, [%r, #%d]\n", work_register, SP_REGNUM,
- offset);
- asm_fprintf (f, "\tmov\t%r, %r\n", work_register, PC_REGNUM);
- asm_fprintf (f, "\tstr\t%r, [%r, #%d]\n", work_register, SP_REGNUM,
- offset + 12);
- }
-
- asm_fprintf (f, "\tmov\t%r, %r\n", work_register, LR_REGNUM);
- asm_fprintf (f, "\tstr\t%r, [%r, #%d]\n", work_register, SP_REGNUM,
- offset + 8);
- asm_fprintf (f, "\tadd\t%r, %r, #%d\n", work_register, SP_REGNUM,
- offset + 12);
- asm_fprintf (f, "\tmov\t%r, %r\t\t%@ Backtrace structure created\n",
- ARM_HARD_FRAME_POINTER_REGNUM, work_register);
- }
- /* Optimization: If we are not pushing any low registers but we are going
- to push some high registers then delay our first push. This will just
- be a push of LR and we can combine it with the push of the first high
- register. */
- else if ((l_mask & 0xff) != 0
- || (high_regs_pushed == 0 && l_mask))
- thumb_pushpop (f, l_mask, 1, &cfa_offset, l_mask);
-
- if (high_regs_pushed)
- {
- unsigned pushable_regs;
- unsigned next_hi_reg;
-
- for (next_hi_reg = 12; next_hi_reg > LAST_LO_REGNUM; next_hi_reg--)
- if (live_regs_mask & (1 << next_hi_reg))
- break;
-
- pushable_regs = l_mask & 0xff;
-
- if (pushable_regs == 0)
- pushable_regs = 1 << thumb_find_work_register (live_regs_mask);
-
- while (high_regs_pushed > 0)
- {
- unsigned long real_regs_mask = 0;
-
- for (regno = LAST_LO_REGNUM; regno >= 0; regno --)
- {
- if (pushable_regs & (1 << regno))
- {
- asm_fprintf (f, "\tmov\t%r, %r\n", regno, next_hi_reg);
-
- high_regs_pushed --;
- real_regs_mask |= (1 << next_hi_reg);
-
- if (high_regs_pushed)
- {
- for (next_hi_reg --; next_hi_reg > LAST_LO_REGNUM;
- next_hi_reg --)
- if (live_regs_mask & (1 << next_hi_reg))
- break;
- }
- else
- {
- pushable_regs &= ~((1 << regno) - 1);
- break;
- }
- }
- }
-
- /* If we had to find a work register and we have not yet
- saved the LR then add it to the list of regs to push. */
- if (l_mask == (1 << LR_REGNUM))
- {
- thumb_pushpop (f, pushable_regs | (1 << LR_REGNUM),
- 1, &cfa_offset,
- real_regs_mask | (1 << LR_REGNUM));
- l_mask = 0;
- }
- else
- thumb_pushpop (f, pushable_regs, 1, &cfa_offset, real_regs_mask);
- }
- }
-}
-
-/* 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. */
-const char *
-thumb_load_double_from_address (rtx *operands)
-{
- rtx addr;
- rtx base;
- rtx offset;
- rtx arg1;
- rtx arg2;
-
- gcc_assert (GET_CODE (operands[0]) == REG);
- gcc_assert (GET_CODE (operands[1]) == MEM);
-
- /* 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] = adjust_address (operands[1], SImode, 4);
-
- if (REGNO (operands[0]) == REGNO (addr))
- {
- output_asm_insn ("ldr\t%H0, %2", operands);
- output_asm_insn ("ldr\t%0, %1", operands);
- }
- else
- {
- output_asm_insn ("ldr\t%0, %1", operands);
- output_asm_insn ("ldr\t%H0, %2", operands);
- }
- break;
-
- case CONST:
- /* Compute <address> + 4 for the high order load. */
- operands[2] = adjust_address (operands[1], SImode, 4);
-
- output_asm_insn ("ldr\t%0, %1", operands);
- output_asm_insn ("ldr\t%H0, %2", 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;
-
- gcc_assert (GET_CODE (base) == REG);
-
- /* 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. */
- asm_fprintf (asm_out_file, "\tadd\t%r, %r, %r",
- reg_dest + 1, reg_base, reg_offset);
-
- /* Load the lower destination register from the address in
- the higher destination register. */
- asm_fprintf (asm_out_file, "\tldr\t%r, [%r, #0]",
- reg_dest, reg_dest + 1);
-
- /* Load the higher destination register from its own address
- plus 4. */
- asm_fprintf (asm_out_file, "\tldr\t%r, [%r, #4]",
- reg_dest + 1, reg_dest + 1);
- }
- else
- {
- /* Compute <address> + 4 for the high order load. */
- operands[2] = adjust_address (operands[1], SImode, 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", operands);
- output_asm_insn ("ldr\t%0, %1", operands);
- }
- else
- {
- output_asm_insn ("ldr\t%0, %1", operands);
- output_asm_insn ("ldr\t%H0, %2", operands);
- }
- }
- break;
-
- case LABEL_REF:
- /* With no registers to worry about we can just load the value
- directly. */
- operands[2] = adjust_address (operands[1], SImode, 4);
-
- output_asm_insn ("ldr\t%H0, %2", operands);
- output_asm_insn ("ldr\t%0, %1", operands);
- break;
-
- default:
- gcc_unreachable ();
- }
-
- return "";
-}
-
-const char *
-thumb_output_move_mem_multiple (int n, rtx *operands)
-{
- rtx tmp;
-
- switch (n)
- {
- case 2:
- if (REGNO (operands[4]) > REGNO (operands[5]))
- {
- tmp = operands[4];
- operands[4] = operands[5];
- operands[5] = tmp;
- }
- output_asm_insn ("ldmia\t%1!, {%4, %5}", operands);
- output_asm_insn ("stmia\t%0!, {%4, %5}", operands);
- break;
-
- case 3:
- if (REGNO (operands[4]) > REGNO (operands[5]))
- {
- tmp = operands[4];
- operands[4] = operands[5];
- operands[5] = tmp;
- }
- if (REGNO (operands[5]) > REGNO (operands[6]))
- {
- tmp = operands[5];
- operands[5] = operands[6];
- operands[6] = tmp;
- }
- if (REGNO (operands[4]) > REGNO (operands[5]))
- {
- tmp = operands[4];
- operands[4] = operands[5];
- operands[5] = tmp;
- }
-
- output_asm_insn ("ldmia\t%1!, {%4, %5, %6}", operands);
- output_asm_insn ("stmia\t%0!, {%4, %5, %6}", operands);
- break;
-
- default:
- gcc_unreachable ();
- }
-
- return "";
-}
-
-/* Output a call-via instruction for thumb state. */
-const char *
-thumb_call_via_reg (rtx reg)
-{
- int regno = REGNO (reg);
- rtx *labelp;
-
- gcc_assert (regno < LR_REGNUM);
-
- /* If we are in the normal text section we can use a single instance
- per compilation unit. If we are doing function sections, then we need
- an entry per section, since we can't rely on reachability. */
- if (in_section == text_section)
- {
- thumb_call_reg_needed = 1;
-
- if (thumb_call_via_label[regno] == NULL)
- thumb_call_via_label[regno] = gen_label_rtx ();
- labelp = thumb_call_via_label + regno;
- }
- else
- {
- if (cfun->machine->call_via[regno] == NULL)
- cfun->machine->call_via[regno] = gen_label_rtx ();
- labelp = cfun->machine->call_via + regno;
- }
-
- output_asm_insn ("bl\t%a0", labelp);
- return "";
-}
-
-/* Routines for generating rtl. */
-void
-thumb_expand_movmemqi (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, out, in));
- len -= 12;
- }
-
- if (len >= 8)
- {
- emit_insn (gen_movmem8b (out, in, 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));
- }
-}
-
-void
-thumb_reload_out_hi (rtx *operands)
-{
- emit_insn (gen_thumb_movhi_clobber (operands[0], operands[1], operands[2]));
-}
-
-/* Handle reading a half-word from memory during reload. */
-void
-thumb_reload_in_hi (rtx *operands ATTRIBUTE_UNUSED)
-{
- gcc_unreachable ();
-}
-
-/* Return the length of a function name prefix
- that starts with the character 'c'. */
-static int
-arm_get_strip_length (int c)
-{
- switch (c)
- {
- ARM_NAME_ENCODING_LENGTHS
- default: return 0;
- }
-}
-
-/* Return a pointer to a function's name with any
- and all prefix encodings stripped from it. */
-const char *
-arm_strip_name_encoding (const char *name)
-{
- int skip;
-
- while ((skip = arm_get_strip_length (* name)))
- name += skip;
-
- return name;
-}
-
-/* If there is a '*' anywhere in the name's prefix, then
- emit the stripped name verbatim, otherwise prepend an
- underscore if leading underscores are being used. */
-void
-arm_asm_output_labelref (FILE *stream, const char *name)
-{
- int skip;
- int verbatim = 0;
-
- while ((skip = arm_get_strip_length (* name)))
- {
- verbatim |= (*name == '*');
- name += skip;
- }
-
- if (verbatim)
- fputs (name, stream);
- else
- asm_fprintf (stream, "%U%s", name);
-}
-
-static void
-arm_file_end (void)
-{
- int regno;
-
- if (NEED_INDICATE_EXEC_STACK)
- /* Add .note.GNU-stack. */
- file_end_indicate_exec_stack ();
-
- if (! thumb_call_reg_needed)
- return;
-
- switch_to_section (text_section);
- asm_fprintf (asm_out_file, "\t.code 16\n");
- ASM_OUTPUT_ALIGN (asm_out_file, 1);
-
- for (regno = 0; regno < LR_REGNUM; regno++)
- {
- rtx label = thumb_call_via_label[regno];
-
- if (label != 0)
- {
- targetm.asm_out.internal_label (asm_out_file, "L",
- CODE_LABEL_NUMBER (label));
- asm_fprintf (asm_out_file, "\tbx\t%r\n", regno);
- }
- }
-}
-
-rtx aof_pic_label;
-
-#ifdef AOF_ASSEMBLER
-/* Special functions only needed when producing AOF syntax assembler. */
-
-struct pic_chain
-{
- struct pic_chain * next;
- const char * symname;
-};
-
-static struct pic_chain * aof_pic_chain = NULL;
-
-rtx
-aof_pic_entry (rtx x)
-{
- struct pic_chain ** chainp;
- int offset;
-
- if (aof_pic_label == NULL_RTX)
- {
- aof_pic_label = gen_rtx_SYMBOL_REF (Pmode, "x$adcons");
- }
-
- for (offset = 0, chainp = &aof_pic_chain; *chainp;
- offset += 4, chainp = &(*chainp)->next)
- if ((*chainp)->symname == XSTR (x, 0))
- return plus_constant (aof_pic_label, offset);
-
- *chainp = (struct pic_chain *) xmalloc (sizeof (struct pic_chain));
- (*chainp)->next = NULL;
- (*chainp)->symname = XSTR (x, 0);
- return plus_constant (aof_pic_label, offset);
-}
-
-void
-aof_dump_pic_table (FILE *f)
-{
- struct pic_chain * chain;
-
- if (aof_pic_chain == NULL)
- return;
-
- asm_fprintf (f, "\tAREA |%r$$adcons|, BASED %r\n",
- PIC_OFFSET_TABLE_REGNUM,
- PIC_OFFSET_TABLE_REGNUM);
- fputs ("|x$adcons|\n", f);
-
- for (chain = aof_pic_chain; chain; chain = chain->next)
- {
- fputs ("\tDCD\t", f);
- assemble_name (f, chain->symname);
- fputs ("\n", f);
- }
-}
-
-int arm_text_section_count = 1;
-
-/* A get_unnamed_section callback for switching to the text section. */
-
-static void
-aof_output_text_section_asm_op (const void *data ATTRIBUTE_UNUSED)
-{
- fprintf (asm_out_file, "\tAREA |C$$code%d|, CODE, READONLY",
- arm_text_section_count++);
- if (flag_pic)
- fprintf (asm_out_file, ", PIC, REENTRANT");
- fprintf (asm_out_file, "\n");
-}
-
-static int arm_data_section_count = 1;
-
-/* A get_unnamed_section callback for switching to the data section. */
-
-static void
-aof_output_data_section_asm_op (const void *data ATTRIBUTE_UNUSED)
-{
- fprintf (asm_out_file, "\tAREA |C$$data%d|, DATA\n",
- arm_data_section_count++);
-}
-
-/* Implement TARGET_ASM_INIT_SECTIONS.
-
- AOF Assembler syntax is a nightmare when it comes to areas, since once
- we change from one area to another, we can't go back again. Instead,
- we must create a new area with the same attributes and add the new output
- to that. Unfortunately, there is nothing we can do here to guarantee that
- two areas with the same attributes will be linked adjacently in the
- resulting executable, so we have to be careful not to do pc-relative
- addressing across such boundaries. */
-
-static void
-aof_asm_init_sections (void)
-{
- text_section = get_unnamed_section (SECTION_CODE,
- aof_output_text_section_asm_op, NULL);
- data_section = get_unnamed_section (SECTION_WRITE,
- aof_output_data_section_asm_op, NULL);
- readonly_data_section = text_section;
-}
-
-void
-zero_init_section (void)
-{
- static int zero_init_count = 1;
-
- fprintf (asm_out_file, "\tAREA |C$$zidata%d|,NOINIT\n", zero_init_count++);
- in_section = NULL;
-}
-
-/* The AOF assembler is religiously strict about declarations of
- imported and exported symbols, so that it is impossible to declare
- a function as imported near the beginning of the file, and then to
- export it later on. It is, however, possible to delay the decision
- until all the functions in the file have been compiled. To get
- around this, we maintain a list of the imports and exports, and
- delete from it any that are subsequently defined. At the end of
- compilation we spit the remainder of the list out before the END
- directive. */
-
-struct import
-{
- struct import * next;
- const char * name;
-};
-
-static struct import * imports_list = NULL;
-
-void
-aof_add_import (const char *name)
-{
- struct import * new;
-
- for (new = imports_list; new; new = new->next)
- if (new->name == name)
- return;
-
- new = (struct import *) xmalloc (sizeof (struct import));
- new->next = imports_list;
- imports_list = new;
- new->name = name;
-}
-
-void
-aof_delete_import (const char *name)
-{
- struct import ** old;
-
- for (old = &imports_list; *old; old = & (*old)->next)
- {
- if ((*old)->name == name)
- {
- *old = (*old)->next;
- return;
- }
- }
-}
-
-int arm_main_function = 0;
-
-static void
-aof_dump_imports (FILE *f)
-{
- /* The AOF assembler needs this to cause the startup code to be extracted
- from the library. Brining in __main causes the whole thing to work
- automagically. */
- if (arm_main_function)
- {
- switch_to_section (text_section);
- fputs ("\tIMPORT __main\n", f);
- fputs ("\tDCD __main\n", f);
- }
-
- /* Now dump the remaining imports. */
- while (imports_list)
- {
- fprintf (f, "\tIMPORT\t");
- assemble_name (f, imports_list->name);
- fputc ('\n', f);
- imports_list = imports_list->next;
- }
-}
-
-static void
-aof_globalize_label (FILE *stream, const char *name)
-{
- default_globalize_label (stream, name);
- if (! strcmp (name, "main"))
- arm_main_function = 1;
-}
-
-static void
-aof_file_start (void)
-{
- fputs ("__r0\tRN\t0\n", asm_out_file);
- fputs ("__a1\tRN\t0\n", asm_out_file);
- fputs ("__a2\tRN\t1\n", asm_out_file);
- fputs ("__a3\tRN\t2\n", asm_out_file);
- fputs ("__a4\tRN\t3\n", asm_out_file);
- fputs ("__v1\tRN\t4\n", asm_out_file);
- fputs ("__v2\tRN\t5\n", asm_out_file);
- fputs ("__v3\tRN\t6\n", asm_out_file);
- fputs ("__v4\tRN\t7\n", asm_out_file);
- fputs ("__v5\tRN\t8\n", asm_out_file);
- fputs ("__v6\tRN\t9\n", asm_out_file);
- fputs ("__sl\tRN\t10\n", asm_out_file);
- fputs ("__fp\tRN\t11\n", asm_out_file);
- fputs ("__ip\tRN\t12\n", asm_out_file);
- fputs ("__sp\tRN\t13\n", asm_out_file);
- fputs ("__lr\tRN\t14\n", asm_out_file);
- fputs ("__pc\tRN\t15\n", asm_out_file);
- fputs ("__f0\tFN\t0\n", asm_out_file);
- fputs ("__f1\tFN\t1\n", asm_out_file);
- fputs ("__f2\tFN\t2\n", asm_out_file);
- fputs ("__f3\tFN\t3\n", asm_out_file);
- fputs ("__f4\tFN\t4\n", asm_out_file);
- fputs ("__f5\tFN\t5\n", asm_out_file);
- fputs ("__f6\tFN\t6\n", asm_out_file);
- fputs ("__f7\tFN\t7\n", asm_out_file);
- switch_to_section (text_section);
-}
-
-static void
-aof_file_end (void)
-{
- if (flag_pic)
- aof_dump_pic_table (asm_out_file);
- arm_file_end ();
- aof_dump_imports (asm_out_file);
- fputs ("\tEND\n", asm_out_file);
-}
-#endif /* AOF_ASSEMBLER */
-
-#ifndef ARM_PE
-/* Symbols in the text segment can be accessed without indirecting via the
- constant pool; it may take an extra binary operation, but this is still
- faster than indirecting via memory. Don't do this when not optimizing,
- since we won't be calculating al of the offsets necessary to do this
- simplification. */
-
-static void
-arm_encode_section_info (tree decl, rtx rtl, int first)
-{
- /* This doesn't work with AOF syntax, since the string table may be in
- a different AREA. */
-#ifndef AOF_ASSEMBLER
- if (optimize > 0 && TREE_CONSTANT (decl))
- SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
-#endif
-
- /* If we are referencing a function that is weak then encode a long call
- flag in the function name, otherwise if the function is static or
- or known to be defined in this file then encode a short call flag. */
- if (first && DECL_P (decl))
- {
- if (TREE_CODE (decl) == FUNCTION_DECL && DECL_WEAK (decl))
- arm_encode_call_attribute (decl, LONG_CALL_FLAG_CHAR);
- else if (! TREE_PUBLIC (decl))
- arm_encode_call_attribute (decl, SHORT_CALL_FLAG_CHAR);
- }
-
- default_encode_section_info (decl, rtl, first);
-}
-#endif /* !ARM_PE */
-
-static void
-arm_internal_label (FILE *stream, const char *prefix, unsigned long labelno)
-{
- if (arm_ccfsm_state == 3 && (unsigned) arm_target_label == labelno
- && !strcmp (prefix, "L"))
- {
- arm_ccfsm_state = 0;
- arm_target_insn = NULL;
- }
- default_internal_label (stream, prefix, labelno);
-}
-
-/* Output code to add DELTA to the first argument, and then jump
- to FUNCTION. Used for C++ multiple inheritance. */
-static void
-arm_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
- HOST_WIDE_INT delta,
- HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
- tree function)
-{
- static int thunk_label = 0;
- char label[256];
- char labelpc[256];
- int mi_delta = delta;
- const char *const mi_op = mi_delta < 0 ? "sub" : "add";
- int shift = 0;
- int this_regno = (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function)
- ? 1 : 0);
- if (mi_delta < 0)
- mi_delta = - mi_delta;
- if (TARGET_THUMB)
- {
- int labelno = thunk_label++;
- ASM_GENERATE_INTERNAL_LABEL (label, "LTHUMBFUNC", labelno);
- fputs ("\tldr\tr12, ", file);
- assemble_name (file, label);
- fputc ('\n', file);
- if (flag_pic)
- {
- /* If we are generating PIC, the ldr instruction below loads
- "(target - 7) - .LTHUNKPCn" into r12. The pc reads as
- the address of the add + 8, so we have:
-
- r12 = (target - 7) - .LTHUNKPCn + (.LTHUNKPCn + 8)
- = target + 1.
-
- Note that we have "+ 1" because some versions of GNU ld
- don't set the low bit of the result for R_ARM_REL32
- relocations against thumb function symbols. */
- ASM_GENERATE_INTERNAL_LABEL (labelpc, "LTHUNKPC", labelno);
- assemble_name (file, labelpc);
- fputs (":\n", file);
- fputs ("\tadd\tr12, pc, r12\n", file);
- }
- }
- while (mi_delta != 0)
- {
- if ((mi_delta & (3 << shift)) == 0)
- shift += 2;
- else
- {
- asm_fprintf (file, "\t%s\t%r, %r, #%d\n",
- mi_op, this_regno, this_regno,
- mi_delta & (0xff << shift));
- mi_delta &= ~(0xff << shift);
- shift += 8;
- }
- }
- if (TARGET_THUMB)
- {
- fprintf (file, "\tbx\tr12\n");
- ASM_OUTPUT_ALIGN (file, 2);
- assemble_name (file, label);
- fputs (":\n", file);
- if (flag_pic)
- {
- /* Output ".word .LTHUNKn-7-.LTHUNKPCn". */
- rtx tem = XEXP (DECL_RTL (function), 0);
- tem = gen_rtx_PLUS (GET_MODE (tem), tem, GEN_INT (-7));
- tem = gen_rtx_MINUS (GET_MODE (tem),
- tem,
- gen_rtx_SYMBOL_REF (Pmode,
- ggc_strdup (labelpc)));
- assemble_integer (tem, 4, BITS_PER_WORD, 1);
- }
- else
- /* Output ".word .LTHUNKn". */
- assemble_integer (XEXP (DECL_RTL (function), 0), 4, BITS_PER_WORD, 1);
- }
- else
- {
- fputs ("\tb\t", file);
- assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
- if (NEED_PLT_RELOC)
- fputs ("(PLT)", file);
- fputc ('\n', file);
- }
-}
-
-int
-arm_emit_vector_const (FILE *file, rtx x)
-{
- int i;
- const char * pattern;
-
- gcc_assert (GET_CODE (x) == CONST_VECTOR);
-
- switch (GET_MODE (x))
- {
- case V2SImode: pattern = "%08x"; break;
- case V4HImode: pattern = "%04x"; break;
- case V8QImode: pattern = "%02x"; break;
- default: gcc_unreachable ();
- }
-
- fprintf (file, "0x");
- for (i = CONST_VECTOR_NUNITS (x); i--;)
- {
- rtx element;
-
- element = CONST_VECTOR_ELT (x, i);
- fprintf (file, pattern, INTVAL (element));
- }
-
- return 1;
-}
-
-const char *
-arm_output_load_gr (rtx *operands)
-{
- rtx reg;
- rtx offset;
- rtx wcgr;
- rtx sum;
-
- if (GET_CODE (operands [1]) != MEM
- || GET_CODE (sum = XEXP (operands [1], 0)) != PLUS
- || GET_CODE (reg = XEXP (sum, 0)) != REG
- || GET_CODE (offset = XEXP (sum, 1)) != CONST_INT
- || ((INTVAL (offset) < 1024) && (INTVAL (offset) > -1024)))
- return "wldrw%?\t%0, %1";
-
- /* Fix up an out-of-range load of a GR register. */
- output_asm_insn ("str%?\t%0, [sp, #-4]!\t@ Start of GR load expansion", & reg);
- wcgr = operands[0];
- operands[0] = reg;
- output_asm_insn ("ldr%?\t%0, %1", operands);
-
- operands[0] = wcgr;
- operands[1] = reg;
- output_asm_insn ("tmcr%?\t%0, %1", operands);
- output_asm_insn ("ldr%?\t%0, [sp], #4\t@ End of GR load expansion", & reg);
-
- return "";
-}
-
-/* Worker function for TARGET_SETUP_INCOMING_VARARGS.
-
- On the ARM, PRETEND_SIZE is set in order to have the prologue push the last
- named arg and all anonymous args onto the stack.
- XXX I know the prologue shouldn't be pushing registers, but it is faster
- that way. */
-
-static void
-arm_setup_incoming_varargs (CUMULATIVE_ARGS *cum,
- enum machine_mode mode ATTRIBUTE_UNUSED,
- tree type ATTRIBUTE_UNUSED,
- int *pretend_size,
- int second_time ATTRIBUTE_UNUSED)
-{
- cfun->machine->uses_anonymous_args = 1;
- if (cum->nregs < NUM_ARG_REGS)
- *pretend_size = (NUM_ARG_REGS - cum->nregs) * UNITS_PER_WORD;
-}
-
-/* Return nonzero if the CONSUMER instruction (a store) does not need
- PRODUCER's value to calculate the address. */
-
-int
-arm_no_early_store_addr_dep (rtx producer, rtx consumer)
-{
- rtx value = PATTERN (producer);
- rtx addr = PATTERN (consumer);
-
- if (GET_CODE (value) == COND_EXEC)
- value = COND_EXEC_CODE (value);
- if (GET_CODE (value) == PARALLEL)
- value = XVECEXP (value, 0, 0);
- value = XEXP (value, 0);
- if (GET_CODE (addr) == COND_EXEC)
- addr = COND_EXEC_CODE (addr);
- if (GET_CODE (addr) == PARALLEL)
- addr = XVECEXP (addr, 0, 0);
- addr = XEXP (addr, 0);
-
- return !reg_overlap_mentioned_p (value, addr);
-}
-
-/* Return nonzero if the CONSUMER instruction (an ALU op) does not
- have an early register shift value or amount dependency on the
- result of PRODUCER. */
-
-int
-arm_no_early_alu_shift_dep (rtx producer, rtx consumer)
-{
- rtx value = PATTERN (producer);
- rtx op = PATTERN (consumer);
- rtx early_op;
-
- if (GET_CODE (value) == COND_EXEC)
- value = COND_EXEC_CODE (value);
- if (GET_CODE (value) == PARALLEL)
- value = XVECEXP (value, 0, 0);
- value = XEXP (value, 0);
- if (GET_CODE (op) == COND_EXEC)
- op = COND_EXEC_CODE (op);
- if (GET_CODE (op) == PARALLEL)
- op = XVECEXP (op, 0, 0);
- op = XEXP (op, 1);
-
- early_op = XEXP (op, 0);
- /* This is either an actual independent shift, or a shift applied to
- the first operand of another operation. We want the whole shift
- operation. */
- if (GET_CODE (early_op) == REG)
- early_op = op;
-
- return !reg_overlap_mentioned_p (value, early_op);
-}
-
-/* Return nonzero if the CONSUMER instruction (an ALU op) does not
- have an early register shift value dependency on the result of
- PRODUCER. */
-
-int
-arm_no_early_alu_shift_value_dep (rtx producer, rtx consumer)
-{
- rtx value = PATTERN (producer);
- rtx op = PATTERN (consumer);
- rtx early_op;
-
- if (GET_CODE (value) == COND_EXEC)
- value = COND_EXEC_CODE (value);
- if (GET_CODE (value) == PARALLEL)
- value = XVECEXP (value, 0, 0);
- value = XEXP (value, 0);
- if (GET_CODE (op) == COND_EXEC)
- op = COND_EXEC_CODE (op);
- if (GET_CODE (op) == PARALLEL)
- op = XVECEXP (op, 0, 0);
- op = XEXP (op, 1);
-
- early_op = XEXP (op, 0);
-
- /* This is either an actual independent shift, or a shift applied to
- the first operand of another operation. We want the value being
- shifted, in either case. */
- if (GET_CODE (early_op) != REG)
- early_op = XEXP (early_op, 0);
-
- return !reg_overlap_mentioned_p (value, early_op);
-}
-
-/* Return nonzero if the CONSUMER (a mul or mac op) does not
- have an early register mult dependency on the result of
- PRODUCER. */
-
-int
-arm_no_early_mul_dep (rtx producer, rtx consumer)
-{
- rtx value = PATTERN (producer);
- rtx op = PATTERN (consumer);
-
- if (GET_CODE (value) == COND_EXEC)
- value = COND_EXEC_CODE (value);
- if (GET_CODE (value) == PARALLEL)
- value = XVECEXP (value, 0, 0);
- value = XEXP (value, 0);
- if (GET_CODE (op) == COND_EXEC)
- op = COND_EXEC_CODE (op);
- if (GET_CODE (op) == PARALLEL)
- op = XVECEXP (op, 0, 0);
- op = XEXP (op, 1);
-
- return (GET_CODE (op) == PLUS
- && !reg_overlap_mentioned_p (value, XEXP (op, 0)));
-}
-
-
-/* We can't rely on the caller doing the proper promotion when
- using APCS or ATPCS. */
-
-static bool
-arm_promote_prototypes (tree t ATTRIBUTE_UNUSED)
-{
- return !TARGET_AAPCS_BASED;
-}
-
-
-/* AAPCS based ABIs use short enums by default. */
-
-static bool
-arm_default_short_enums (void)
-{
- return TARGET_AAPCS_BASED && arm_abi != ARM_ABI_AAPCS_LINUX;
-}
-
-
-/* AAPCS requires that anonymous bitfields affect structure alignment. */
-
-static bool
-arm_align_anon_bitfield (void)
-{
- return TARGET_AAPCS_BASED;
-}
-
-
-/* The generic C++ ABI says 64-bit (long long). The EABI says 32-bit. */
-
-static tree
-arm_cxx_guard_type (void)
-{
- return TARGET_AAPCS_BASED ? integer_type_node : long_long_integer_type_node;
-}
-
-
-/* The EABI says test the least significant bit of a guard variable. */
-
-static bool
-arm_cxx_guard_mask_bit (void)
-{
- return TARGET_AAPCS_BASED;
-}
-
-
-/* The EABI specifies that all array cookies are 8 bytes long. */
-
-static tree
-arm_get_cookie_size (tree type)
-{
- tree size;
-
- if (!TARGET_AAPCS_BASED)
- return default_cxx_get_cookie_size (type);
-
- size = build_int_cst (sizetype, 8);
- return size;
-}
-
-
-/* The EABI says that array cookies should also contain the element size. */
-
-static bool
-arm_cookie_has_size (void)
-{
- return TARGET_AAPCS_BASED;
-}
-
-
-/* The EABI says constructors and destructors should return a pointer to
- the object constructed/destroyed. */
-
-static bool
-arm_cxx_cdtor_returns_this (void)
-{
- return TARGET_AAPCS_BASED;
-}
-
-/* The EABI says that an inline function may never be the key
- method. */
-
-static bool
-arm_cxx_key_method_may_be_inline (void)
-{
- return !TARGET_AAPCS_BASED;
-}
-
-static void
-arm_cxx_determine_class_data_visibility (tree decl)
-{
- if (!TARGET_AAPCS_BASED)
- return;
-
- /* In general, \S 3.2.5.5 of the ARM EABI requires that class data
- is exported. However, on systems without dynamic vague linkage,
- \S 3.2.5.6 says that COMDAT class data has hidden linkage. */
- if (!TARGET_ARM_DYNAMIC_VAGUE_LINKAGE_P && DECL_COMDAT (decl))
- DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
- else
- DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
- DECL_VISIBILITY_SPECIFIED (decl) = 1;
-}
-
-static bool
-arm_cxx_class_data_always_comdat (void)
-{
- /* \S 3.2.5.4 of the ARM C++ ABI says that class data only have
- vague linkage if the class has no key function. */
- return !TARGET_AAPCS_BASED;
-}
-
-
-/* The EABI says __aeabi_atexit should be used to register static
- destructors. */
-
-static bool
-arm_cxx_use_aeabi_atexit (void)
-{
- return TARGET_AAPCS_BASED;
-}
-
-
-void
-arm_set_return_address (rtx source, rtx scratch)
-{
- arm_stack_offsets *offsets;
- HOST_WIDE_INT delta;
- rtx addr;
- unsigned long saved_regs;
-
- saved_regs = arm_compute_save_reg_mask ();
-
- if ((saved_regs & (1 << LR_REGNUM)) == 0)
- emit_move_insn (gen_rtx_REG (Pmode, LR_REGNUM), source);
- else
- {
- if (frame_pointer_needed)
- addr = plus_constant(hard_frame_pointer_rtx, -4);
- else
- {
- /* LR will be the first saved register. */
- offsets = arm_get_frame_offsets ();
- delta = offsets->outgoing_args - (offsets->frame + 4);
-
-
- if (delta >= 4096)
- {
- emit_insn (gen_addsi3 (scratch, stack_pointer_rtx,
- GEN_INT (delta & ~4095)));
- addr = scratch;
- delta &= 4095;
- }
- else
- addr = stack_pointer_rtx;
-
- addr = plus_constant (addr, delta);
- }
- emit_move_insn (gen_frame_mem (Pmode, addr), source);
- }
-}
-
-
-void
-thumb_set_return_address (rtx source, rtx scratch)
-{
- arm_stack_offsets *offsets;
- HOST_WIDE_INT delta;
- int reg;
- rtx addr;
- unsigned long mask;
-
- emit_insn (gen_rtx_USE (VOIDmode, source));
-
- mask = thumb_compute_save_reg_mask ();
- if (mask & (1 << LR_REGNUM))
- {
- offsets = arm_get_frame_offsets ();
-
- /* Find the saved regs. */
- if (frame_pointer_needed)
- {
- delta = offsets->soft_frame - offsets->saved_args;
- reg = THUMB_HARD_FRAME_POINTER_REGNUM;
- }
- else
- {
- delta = offsets->outgoing_args - offsets->saved_args;
- reg = SP_REGNUM;
- }
- /* Allow for the stack frame. */
- if (TARGET_BACKTRACE)
- delta -= 16;
- /* The link register is always the first saved register. */
- delta -= 4;
-
- /* Construct the address. */
- addr = gen_rtx_REG (SImode, reg);
- if ((reg != SP_REGNUM && delta >= 128)
- || delta >= 1024)
- {
- emit_insn (gen_movsi (scratch, GEN_INT (delta)));
- emit_insn (gen_addsi3 (scratch, scratch, stack_pointer_rtx));
- addr = scratch;
- }
- else
- addr = plus_constant (addr, delta);
-
- emit_move_insn (gen_frame_mem (Pmode, addr), source);
- }
- else
- emit_move_insn (gen_rtx_REG (Pmode, LR_REGNUM), source);
-}
-
-/* Implements target hook vector_mode_supported_p. */
-bool
-arm_vector_mode_supported_p (enum machine_mode mode)
-{
- if ((mode == V2SImode)
- || (mode == V4HImode)
- || (mode == V8QImode))
- return true;
-
- return false;
-}
-
-/* Implement TARGET_SHIFT_TRUNCATION_MASK. SImode shifts use normal
- ARM insns and therefore guarantee that the shift count is modulo 256.
- DImode shifts (those implemented by lib1funcs.asm or by optabs.c)
- guarantee no particular behavior for out-of-range counts. */
-
-static unsigned HOST_WIDE_INT
-arm_shift_truncation_mask (enum machine_mode mode)
-{
- return mode == SImode ? 255 : 0;
-}
-
-
-/* Map internal gcc register numbers to DWARF2 register numbers. */
-
-unsigned int
-arm_dbx_register_number (unsigned int regno)
-{
- if (regno < 16)
- return regno;
-
- /* TODO: Legacy targets output FPA regs as registers 16-23 for backwards
- compatibility. The EABI defines them as registers 96-103. */
- if (IS_FPA_REGNUM (regno))
- return (TARGET_AAPCS_BASED ? 96 : 16) + regno - FIRST_FPA_REGNUM;
-
- if (IS_VFP_REGNUM (regno))
- return 64 + regno - FIRST_VFP_REGNUM;
-
- if (IS_IWMMXT_GR_REGNUM (regno))
- return 104 + regno - FIRST_IWMMXT_GR_REGNUM;
-
- if (IS_IWMMXT_REGNUM (regno))
- return 112 + regno - FIRST_IWMMXT_REGNUM;
-
- gcc_unreachable ();
-}
-
-
-#ifdef TARGET_UNWIND_INFO
-/* Emit unwind directives for a store-multiple instruction. This should
- only ever be generated by the function prologue code, so we expect it
- to have a particular form. */
-
-static void
-arm_unwind_emit_stm (FILE * asm_out_file, rtx p)
-{
- int i;
- HOST_WIDE_INT offset;
- HOST_WIDE_INT nregs;
- int reg_size;
- unsigned reg;
- unsigned lastreg;
- rtx e;
-
- /* First insn will adjust the stack pointer. */
- e = XVECEXP (p, 0, 0);
- if (GET_CODE (e) != SET
- || GET_CODE (XEXP (e, 0)) != REG
- || REGNO (XEXP (e, 0)) != SP_REGNUM
- || GET_CODE (XEXP (e, 1)) != PLUS)
- abort ();
-
- offset = -INTVAL (XEXP (XEXP (e, 1), 1));
- nregs = XVECLEN (p, 0) - 1;
-
- reg = REGNO (XEXP (XVECEXP (p, 0, 1), 1));
- if (reg < 16)
- {
- /* The function prologue may also push pc, but not annotate it as it is
- never restored. We turn this into a stack pointer adjustment. */
- if (nregs * 4 == offset - 4)
- {
- fprintf (asm_out_file, "\t.pad #4\n");
- offset -= 4;
- }
- reg_size = 4;
- }
- else if (IS_VFP_REGNUM (reg))
- {
- /* FPA register saves use an additional word. */
- offset -= 4;
- reg_size = 8;
- }
- else if (reg >= FIRST_FPA_REGNUM && reg <= LAST_FPA_REGNUM)
- {
- /* FPA registers are done differently. */
- asm_fprintf (asm_out_file, "\t.save %r, %wd\n", reg, nregs);
- return;
- }
- else
- /* Unknown register type. */
- abort ();
-
- /* If the stack increment doesn't match the size of the saved registers,
- something has gone horribly wrong. */
- if (offset != nregs * reg_size)
- abort ();
-
- fprintf (asm_out_file, "\t.save {");
-
- offset = 0;
- lastreg = 0;
- /* The remaining insns will describe the stores. */
- for (i = 1; i <= nregs; i++)
- {
- /* Expect (set (mem <addr>) (reg)).
- Where <addr> is (reg:SP) or (plus (reg:SP) (const_int)). */
- e = XVECEXP (p, 0, i);
- if (GET_CODE (e) != SET
- || GET_CODE (XEXP (e, 0)) != MEM
- || GET_CODE (XEXP (e, 1)) != REG)
- abort ();
-
- reg = REGNO (XEXP (e, 1));
- if (reg < lastreg)
- abort ();
-
- if (i != 1)
- fprintf (asm_out_file, ", ");
- /* We can't use %r for vfp because we need to use the
- double precision register names. */
- if (IS_VFP_REGNUM (reg))
- asm_fprintf (asm_out_file, "d%d", (reg - FIRST_VFP_REGNUM) / 2);
- else
- asm_fprintf (asm_out_file, "%r", reg);
-
-#ifdef ENABLE_CHECKING
- /* Check that the addresses are consecutive. */
- e = XEXP (XEXP (e, 0), 0);
- if (GET_CODE (e) == PLUS)
- {
- offset += reg_size;
- if (GET_CODE (XEXP (e, 0)) != REG
- || REGNO (XEXP (e, 0)) != SP_REGNUM
- || GET_CODE (XEXP (e, 1)) != CONST_INT
- || offset != INTVAL (XEXP (e, 1)))
- abort ();
- }
- else if (i != 1
- || GET_CODE (e) != REG
- || REGNO (e) != SP_REGNUM)
- abort ();
-#endif
- }
- fprintf (asm_out_file, "}\n");
-}
-
-/* Emit unwind directives for a SET. */
-
-static void
-arm_unwind_emit_set (FILE * asm_out_file, rtx p)
-{
- rtx e0;
- rtx e1;
-
- e0 = XEXP (p, 0);
- e1 = XEXP (p, 1);
- switch (GET_CODE (e0))
- {
- case MEM:
- /* Pushing a single register. */
- if (GET_CODE (XEXP (e0, 0)) != PRE_DEC
- || GET_CODE (XEXP (XEXP (e0, 0), 0)) != REG
- || REGNO (XEXP (XEXP (e0, 0), 0)) != SP_REGNUM)
- abort ();
-
- asm_fprintf (asm_out_file, "\t.save ");
- if (IS_VFP_REGNUM (REGNO (e1)))
- asm_fprintf(asm_out_file, "{d%d}\n",
- (REGNO (e1) - FIRST_VFP_REGNUM) / 2);
- else
- asm_fprintf(asm_out_file, "{%r}\n", REGNO (e1));
- break;
-
- case REG:
- if (REGNO (e0) == SP_REGNUM)
- {
- /* A stack increment. */
- if (GET_CODE (e1) != PLUS
- || GET_CODE (XEXP (e1, 0)) != REG
- || REGNO (XEXP (e1, 0)) != SP_REGNUM
- || GET_CODE (XEXP (e1, 1)) != CONST_INT)
- abort ();
-
- asm_fprintf (asm_out_file, "\t.pad #%wd\n",
- -INTVAL (XEXP (e1, 1)));
- }
- else if (REGNO (e0) == HARD_FRAME_POINTER_REGNUM)
- {
- HOST_WIDE_INT offset;
- unsigned reg;
-
- if (GET_CODE (e1) == PLUS)
- {
- if (GET_CODE (XEXP (e1, 0)) != REG
- || GET_CODE (XEXP (e1, 1)) != CONST_INT)
- abort ();
- reg = REGNO (XEXP (e1, 0));
- offset = INTVAL (XEXP (e1, 1));
- asm_fprintf (asm_out_file, "\t.setfp %r, %r, #%wd\n",
- HARD_FRAME_POINTER_REGNUM, reg,
- INTVAL (XEXP (e1, 1)));
- }
- else if (GET_CODE (e1) == REG)
- {
- reg = REGNO (e1);
- asm_fprintf (asm_out_file, "\t.setfp %r, %r\n",
- HARD_FRAME_POINTER_REGNUM, reg);
- }
- else
- abort ();
- }
- else if (GET_CODE (e1) == REG && REGNO (e1) == SP_REGNUM)
- {
- /* Move from sp to reg. */
- asm_fprintf (asm_out_file, "\t.movsp %r\n", REGNO (e0));
- }
- else if (GET_CODE (e1) == PLUS
- && GET_CODE (XEXP (e1, 0)) == REG
- && REGNO (XEXP (e1, 0)) == SP_REGNUM
- && GET_CODE (XEXP (e1, 1)) == CONST_INT)
- {
- /* Set reg to offset from sp. */
- asm_fprintf (asm_out_file, "\t.movsp %r, #%d\n",
- REGNO (e0), (int)INTVAL(XEXP (e1, 1)));
- }
- else
- abort ();
- break;
-
- default:
- abort ();
- }
-}
-
-
-/* Emit unwind directives for the given insn. */
-
-static void
-arm_unwind_emit (FILE * asm_out_file, rtx insn)
-{
- rtx pat;
-
- if (!ARM_EABI_UNWIND_TABLES)
- return;
-
- if (GET_CODE (insn) == NOTE || !RTX_FRAME_RELATED_P (insn))
- return;
-
- pat = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
- if (pat)
- pat = XEXP (pat, 0);
- else
- pat = PATTERN (insn);
-
- switch (GET_CODE (pat))
- {
- case SET:
- arm_unwind_emit_set (asm_out_file, pat);
- break;
-
- case SEQUENCE:
- /* Store multiple. */
- arm_unwind_emit_stm (asm_out_file, pat);
- break;
-
- default:
- abort();
- }
-}
-
-
-/* Output a reference from a function exception table to the type_info
- object X. The EABI specifies that the symbol should be relocated by
- an R_ARM_TARGET2 relocation. */
-
-static bool
-arm_output_ttype (rtx x)
-{
- fputs ("\t.word\t", asm_out_file);
- output_addr_const (asm_out_file, x);
- /* Use special relocations for symbol references. */
- if (GET_CODE (x) != CONST_INT)
- fputs ("(TARGET2)", asm_out_file);
- fputc ('\n', asm_out_file);
-
- return TRUE;
-}
-#endif /* TARGET_UNWIND_INFO */
-
-
-/* Output unwind directives for the start/end of a function. */
-
-void
-arm_output_fn_unwind (FILE * f, bool prologue)
-{
- if (!ARM_EABI_UNWIND_TABLES)
- return;
-
- if (prologue)
- fputs ("\t.fnstart\n", f);
- else
- fputs ("\t.fnend\n", f);
-}
-
-static bool
-arm_emit_tls_decoration (FILE *fp, rtx x)
-{
- enum tls_reloc reloc;
- rtx val;
-
- val = XVECEXP (x, 0, 0);
- reloc = INTVAL (XVECEXP (x, 0, 1));
-
- output_addr_const (fp, val);
-
- switch (reloc)
- {
- case TLS_GD32:
- fputs ("(tlsgd)", fp);
- break;
- case TLS_LDM32:
- fputs ("(tlsldm)", fp);
- break;
- case TLS_LDO32:
- fputs ("(tlsldo)", fp);
- break;
- case TLS_IE32:
- fputs ("(gottpoff)", fp);
- break;
- case TLS_LE32:
- fputs ("(tpoff)", fp);
- break;
- default:
- gcc_unreachable ();
- }
-
- switch (reloc)
- {
- case TLS_GD32:
- case TLS_LDM32:
- case TLS_IE32:
- fputs (" + (. - ", fp);
- output_addr_const (fp, XVECEXP (x, 0, 2));
- fputs (" - ", fp);
- output_addr_const (fp, XVECEXP (x, 0, 3));
- fputc (')', fp);
- break;
- default:
- break;
- }
-
- return TRUE;
-}
-
-bool
-arm_output_addr_const_extra (FILE *fp, rtx x)
-{
- if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLS)
- return arm_emit_tls_decoration (fp, x);
- else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_PIC_LABEL)
- {
- char label[256];
- int labelno = INTVAL (XVECEXP (x, 0, 0));
-
- ASM_GENERATE_INTERNAL_LABEL (label, "LPIC", labelno);
- assemble_name_raw (fp, label);
-
- return TRUE;
- }
- else if (GET_CODE (x) == CONST_VECTOR)
- return arm_emit_vector_const (fp, x);
-
- return FALSE;
-}
-
-#include "gt-arm.h"
diff --git a/gcc-4.2.1/gcc/config/arm/arm.h b/gcc-4.2.1/gcc/config/arm/arm.h
deleted file mode 100644
index d4cb3d686..000000000
--- a/gcc-4.2.1/gcc/config/arm/arm.h
+++ /dev/null
@@ -1,2604 +0,0 @@
-/* Definitions of target machine for GNU compiler, for ARM.
- Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
- Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
- and Martin Simmons (@harleqn.co.uk).
- More major hacks by Richard Earnshaw (rearnsha@arm.com)
- Minor hacks by Nick Clifton (nickc@cygnus.com)
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
- MA 02110-1301, USA. */
-
-#ifndef GCC_ARM_H
-#define GCC_ARM_H
-
-/* The architecture define. */
-extern char arm_arch_name[];
-
-/* Target CPU builtins. */
-#define TARGET_CPU_CPP_BUILTINS() \
- do \
- { \
- /* Define __arm__ even when in thumb mode, for \
- consistency with armcc. */ \
- builtin_define ("__arm__"); \
- builtin_define ("__APCS_32__"); \
- if (TARGET_THUMB) \
- builtin_define ("__thumb__"); \
- \
- if (TARGET_BIG_END) \
- { \
- builtin_define ("__ARMEB__"); \
- if (TARGET_THUMB) \
- builtin_define ("__THUMBEB__"); \
- if (TARGET_LITTLE_WORDS) \
- builtin_define ("__ARMWEL__"); \
- } \
- else \
- { \
- builtin_define ("__ARMEL__"); \
- if (TARGET_THUMB) \
- builtin_define ("__THUMBEL__"); \
- } \
- \
- if (TARGET_SOFT_FLOAT) \
- builtin_define ("__SOFTFP__"); \
- \
- if (TARGET_VFP) \
- builtin_define ("__VFP_FP__"); \
- \
- /* Add a define for interworking. \
- Needed when building libgcc.a. */ \
- if (arm_cpp_interwork) \
- builtin_define ("__THUMB_INTERWORK__"); \
- \
- builtin_assert ("cpu=arm"); \
- builtin_assert ("machine=arm"); \
- \
- builtin_define (arm_arch_name); \
- if (arm_arch_cirrus) \
- builtin_define ("__MAVERICK__"); \
- if (arm_arch_xscale) \
- builtin_define ("__XSCALE__"); \
- if (arm_arch_iwmmxt) \
- builtin_define ("__IWMMXT__"); \
- if (TARGET_AAPCS_BASED) \
- builtin_define ("__ARM_EABI__"); \
- } while (0)
-
-/* The various ARM cores. */
-enum processor_type
-{
-#define ARM_CORE(NAME, IDENT, ARCH, FLAGS, COSTS) \
- IDENT,
-#include "arm-cores.def"
-#undef ARM_CORE
- /* Used to indicate that no processor has been specified. */
- arm_none
-};
-
-enum target_cpus
-{
-#define ARM_CORE(NAME, IDENT, ARCH, FLAGS, COSTS) \
- TARGET_CPU_##IDENT,
-#include "arm-cores.def"
-#undef ARM_CORE
- TARGET_CPU_generic
-};
-
-/* The processor for which instructions should be scheduled. */
-extern enum processor_type arm_tune;
-
-typedef enum arm_cond_code
-{
- ARM_EQ = 0, ARM_NE, ARM_CS, ARM_CC, ARM_MI, ARM_PL, ARM_VS, ARM_VC,
- ARM_HI, ARM_LS, ARM_GE, ARM_LT, ARM_GT, ARM_LE, ARM_AL, ARM_NV
-}
-arm_cc;
-
-extern arm_cc arm_current_cc;
-
-#define ARM_INVERSE_CONDITION_CODE(X) ((arm_cc) (((int)X) ^ 1))
-
-extern int arm_target_label;
-extern int arm_ccfsm_state;
-extern GTY(()) rtx arm_target_insn;
-/* Define the information needed to generate branch insns. This is
- stored from the compare operation. */
-extern GTY(()) rtx arm_compare_op0;
-extern GTY(()) rtx arm_compare_op1;
-/* The label of the current constant pool. */
-extern rtx pool_vector_label;
-/* Set to 1 when a return insn is output, this means that the epilogue
- is not needed. */
-extern int return_used_this_function;
-/* Used to produce AOF syntax assembler. */
-extern GTY(()) rtx aof_pic_label;
-
-/* Just in case configure has failed to define anything. */
-#ifndef TARGET_CPU_DEFAULT
-#define TARGET_CPU_DEFAULT TARGET_CPU_generic
-#endif
-
-
-#undef CPP_SPEC
-#define CPP_SPEC "%(subtarget_cpp_spec) \
-%{msoft-float:%{mhard-float: \
- %e-msoft-float and -mhard_float may not be used together}} \
-%{mbig-endian:%{mlittle-endian: \
- %e-mbig-endian and -mlittle-endian may not be used together}}"
-
-#ifndef CC1_SPEC
-#define CC1_SPEC ""
-#endif
-
-/* This macro defines names of additional specifications to put in the specs
- that can be used in various specifications like CC1_SPEC. Its definition
- is an initializer with a subgrouping for each command option.
-
- Each subgrouping contains a string constant, that defines the
- specification name, and a string constant that used by the GCC driver
- program.
-
- Do not define this macro if it does not need to do anything. */
-#define EXTRA_SPECS \
- { "subtarget_cpp_spec", SUBTARGET_CPP_SPEC }, \
- SUBTARGET_EXTRA_SPECS
-
-#ifndef SUBTARGET_EXTRA_SPECS
-#define SUBTARGET_EXTRA_SPECS
-#endif
-
-#ifndef SUBTARGET_CPP_SPEC
-#define SUBTARGET_CPP_SPEC ""
-#endif
-
-/* Run-time Target Specification. */
-#ifndef TARGET_VERSION
-#define TARGET_VERSION fputs (" (ARM/generic)", stderr);
-#endif
-
-#define TARGET_SOFT_FLOAT (arm_float_abi == ARM_FLOAT_ABI_SOFT)
-/* Use hardware floating point instructions. */
-#define TARGET_HARD_FLOAT (arm_float_abi != ARM_FLOAT_ABI_SOFT)
-/* Use hardware floating point calling convention. */
-#define TARGET_HARD_FLOAT_ABI (arm_float_abi == ARM_FLOAT_ABI_HARD)
-#define TARGET_FPA (arm_fp_model == ARM_FP_MODEL_FPA)
-#define TARGET_MAVERICK (arm_fp_model == ARM_FP_MODEL_MAVERICK)
-#define TARGET_VFP (arm_fp_model == ARM_FP_MODEL_VFP)
-#define TARGET_IWMMXT (arm_arch_iwmmxt)
-#define TARGET_REALLY_IWMMXT (TARGET_IWMMXT && TARGET_ARM)
-#define TARGET_IWMMXT_ABI (TARGET_ARM && arm_abi == ARM_ABI_IWMMXT)
-#define TARGET_ARM (! TARGET_THUMB)
-#define TARGET_EITHER 1 /* (TARGET_ARM | TARGET_THUMB) */
-#define TARGET_BACKTRACE (leaf_function_p () \
- ? TARGET_TPCS_LEAF_FRAME \
- : TARGET_TPCS_FRAME)
-#define TARGET_LDRD (arm_arch5e && ARM_DOUBLEWORD_ALIGN)
-#define TARGET_AAPCS_BASED \
- (arm_abi != ARM_ABI_APCS && arm_abi != ARM_ABI_ATPCS)
-
-#define TARGET_HARD_TP (target_thread_pointer == TP_CP15)
-#define TARGET_SOFT_TP (target_thread_pointer == TP_SOFT)
-
-/* True iff the full BPABI is being used. If TARGET_BPABI is true,
- then TARGET_AAPCS_BASED must be true -- but the converse does not
- hold. TARGET_BPABI implies the use of the BPABI runtime library,
- etc., in addition to just the AAPCS calling conventions. */
-#ifndef TARGET_BPABI
-#define TARGET_BPABI false
-#endif
-
-/* Support for a compile-time default CPU, et cetera. The rules are:
- --with-arch is ignored if -march or -mcpu are specified.
- --with-cpu is ignored if -march or -mcpu are specified, and is overridden
- by --with-arch.
- --with-tune is ignored if -mtune or -mcpu are specified (but not affected
- by -march).
- --with-float is ignored if -mhard-float, -msoft-float or -mfloat-abi are
- specified.
- --with-fpu is ignored if -mfpu is specified.
- --with-abi is ignored is -mabi is specified. */
-#define OPTION_DEFAULT_SPECS \
- {"arch", "%{!march=*:%{!mcpu=*:-march=%(VALUE)}}" }, \
- {"cpu", "%{!march=*:%{!mcpu=*:-mcpu=%(VALUE)}}" }, \
- {"tune", "%{!mcpu=*:%{!mtune=*:-mtune=%(VALUE)}}" }, \
- {"float", \
- "%{!msoft-float:%{!mhard-float:%{!mfloat-abi=*:-mfloat-abi=%(VALUE)}}}" }, \
- {"fpu", "%{!mfpu=*:-mfpu=%(VALUE)}"}, \
- {"abi", "%{!mabi=*:-mabi=%(VALUE)}"}, \
- {"mode", "%{!marm:%{!mthumb:-m%(VALUE)}}"},
-
-/* Which floating point model to use. */
-enum arm_fp_model
-{
- ARM_FP_MODEL_UNKNOWN,
- /* FPA model (Hardware or software). */
- ARM_FP_MODEL_FPA,
- /* Cirrus Maverick floating point model. */
- ARM_FP_MODEL_MAVERICK,
- /* VFP floating point model. */
- ARM_FP_MODEL_VFP
-};
-
-extern enum arm_fp_model arm_fp_model;
-
-/* Which floating point hardware is available. Also update
- fp_model_for_fpu in arm.c when adding entries to this list. */
-enum fputype
-{
- /* No FP hardware. */
- FPUTYPE_NONE,
- /* Full FPA support. */
- FPUTYPE_FPA,
- /* Emulated FPA hardware, Issue 2 emulator (no LFM/SFM). */
- FPUTYPE_FPA_EMU2,
- /* Emulated FPA hardware, Issue 3 emulator. */
- FPUTYPE_FPA_EMU3,
- /* Cirrus Maverick floating point co-processor. */
- FPUTYPE_MAVERICK,
- /* VFP. */
- FPUTYPE_VFP
-};
-
-/* Recast the floating point class to be the floating point attribute. */
-#define arm_fpu_attr ((enum attr_fpu) arm_fpu_tune)
-
-/* What type of floating point to tune for */
-extern enum fputype arm_fpu_tune;
-
-/* What type of floating point instructions are available */
-extern enum fputype arm_fpu_arch;
-
-enum float_abi_type
-{
- ARM_FLOAT_ABI_SOFT,
- ARM_FLOAT_ABI_SOFTFP,
- ARM_FLOAT_ABI_HARD
-};
-
-extern enum float_abi_type arm_float_abi;
-
-#ifndef TARGET_DEFAULT_FLOAT_ABI
-#define TARGET_DEFAULT_FLOAT_ABI ARM_FLOAT_ABI_SOFT
-#endif
-
-/* Which ABI to use. */
-enum arm_abi_type
-{
- ARM_ABI_APCS,
- ARM_ABI_ATPCS,
- ARM_ABI_AAPCS,
- ARM_ABI_IWMMXT,
- ARM_ABI_AAPCS_LINUX
-};
-
-extern enum arm_abi_type arm_abi;
-
-#ifndef ARM_DEFAULT_ABI
-#define ARM_DEFAULT_ABI ARM_ABI_APCS
-#endif
-
-/* Which thread pointer access sequence to use. */
-enum arm_tp_type {
- TP_AUTO,
- TP_SOFT,
- TP_CP15
-};
-
-extern enum arm_tp_type target_thread_pointer;
-
-/* Nonzero if this chip supports the ARM Architecture 3M extensions. */
-extern int arm_arch3m;
-
-/* Nonzero if this chip supports the ARM Architecture 4 extensions. */
-extern int arm_arch4;
-
-/* Nonzero if this chip supports the ARM Architecture 4T extensions. */
-extern int arm_arch4t;
-
-/* Nonzero if this chip supports the ARM Architecture 5 extensions. */
-extern int arm_arch5;
-
-/* Nonzero if this chip supports the ARM Architecture 5E extensions. */
-extern int arm_arch5e;
-
-/* Nonzero if this chip supports the ARM Architecture 6 extensions. */
-extern int arm_arch6;
-
-/* Nonzero if this chip can benefit from load scheduling. */
-extern int arm_ld_sched;
-
-/* Nonzero if generating thumb code. */
-extern int thumb_code;
-
-/* Nonzero if this chip is a StrongARM. */
-extern int arm_tune_strongarm;
-
-/* Nonzero if this chip is a Cirrus variant. */
-extern int arm_arch_cirrus;
-
-/* Nonzero if this chip supports Intel XScale with Wireless MMX technology. */
-extern int arm_arch_iwmmxt;
-
-/* Nonzero if this chip is an XScale. */
-extern int arm_arch_xscale;
-
-/* Nonzero if tuning for XScale. */
-extern int arm_tune_xscale;
-
-/* Nonzero if tuning for stores via the write buffer. */
-extern int arm_tune_wbuf;
-
-/* Nonzero if we should define __THUMB_INTERWORK__ in the
- preprocessor.
- XXX This is a bit of a hack, it's intended to help work around
- problems in GLD which doesn't understand that armv5t code is
- interworking clean. */
-extern int arm_cpp_interwork;
-
-#ifndef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_APCS_FRAME)
-#endif
-
-/* The frame pointer register used in gcc has nothing to do with debugging;
- that is controlled by the APCS-FRAME option. */
-#define CAN_DEBUG_WITHOUT_FP
-
-#define OVERRIDE_OPTIONS arm_override_options ()
-
-/* Nonzero if PIC code requires explicit qualifiers to generate
- PLT and GOT relocs rather than the assembler doing so implicitly.
- Subtargets can override these if required. */
-#ifndef NEED_GOT_RELOC
-#define NEED_GOT_RELOC 0
-#endif
-#ifndef NEED_PLT_RELOC
-#define NEED_PLT_RELOC 0
-#endif
-
-/* Nonzero if we need to refer to the GOT with a PC-relative
- offset. In other words, generate
-
- .word _GLOBAL_OFFSET_TABLE_ - [. - (.Lxx + 8)]
-
- rather than
-
- .word _GLOBAL_OFFSET_TABLE_ - (.Lxx + 8)
-
- The default is true, which matches NetBSD. Subtargets can
- override this if required. */
-#ifndef GOT_PCREL
-#define GOT_PCREL 1
-#endif
-
-/* Target machine storage Layout. */
-
-
-/* Define this macro if it is advisable to hold scalars in registers
- in a wider mode than that declared by the program. In such cases,
- the value is constrained to be within the bounds of the declared
- type, but kept valid in the wider mode. The signedness of the
- extension may differ from that of the type. */
-
-/* It is far faster to zero extend chars than to sign extend them */
-
-#define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE) \
- if (GET_MODE_CLASS (MODE) == MODE_INT \
- && GET_MODE_SIZE (MODE) < 4) \
- { \
- if (MODE == QImode) \
- UNSIGNEDP = 1; \
- else if (MODE == HImode) \
- UNSIGNEDP = 1; \
- (MODE) = SImode; \
- }
-
-#define PROMOTE_FUNCTION_MODE(MODE, UNSIGNEDP, TYPE) \
- if ((GET_MODE_CLASS (MODE) == MODE_INT \
- || GET_MODE_CLASS (MODE) == MODE_COMPLEX_INT) \
- && GET_MODE_SIZE (MODE) < 4) \
- (MODE) = SImode; \
-
-/* Define this if most significant bit is lowest numbered
- in instructions that operate on numbered bit-fields. */
-#define BITS_BIG_ENDIAN 0
-
-/* Define this if most significant byte of a word is the lowest numbered.
- Most ARM processors are run in little endian mode, so that is the default.
- If you want to have it run-time selectable, change the definition in a
- cover file to be TARGET_BIG_ENDIAN. */
-#define BYTES_BIG_ENDIAN (TARGET_BIG_END != 0)
-
-/* Define this if most significant word of a multiword number is the lowest
- numbered.
- This is always false, even when in big-endian mode. */
-#define WORDS_BIG_ENDIAN (BYTES_BIG_ENDIAN && ! TARGET_LITTLE_WORDS)
-
-/* LIBGCC2_WORDS_BIG_ENDIAN has to be a constant, so we define this based
- on processor pre-defineds when compiling libgcc2.c. */
-#if defined(__ARMEB__) && !defined(__ARMWEL__)
-#define LIBGCC2_WORDS_BIG_ENDIAN 1
-#else
-#define LIBGCC2_WORDS_BIG_ENDIAN 0
-#endif
-
-/* Define this if most significant word of doubles is the lowest numbered.
- The rules are different based on whether or not we use FPA-format,
- VFP-format or some other floating point co-processor's format doubles. */
-#define FLOAT_WORDS_BIG_ENDIAN (arm_float_words_big_endian ())
-
-#define UNITS_PER_WORD 4
-
-/* True if natural alignment is used for doubleword types. */
-#define ARM_DOUBLEWORD_ALIGN TARGET_AAPCS_BASED
-
-#define DOUBLEWORD_ALIGNMENT 64
-
-#define PARM_BOUNDARY 32
-
-#define STACK_BOUNDARY (ARM_DOUBLEWORD_ALIGN ? DOUBLEWORD_ALIGNMENT : 32)
-
-#define PREFERRED_STACK_BOUNDARY \
- (arm_abi == ARM_ABI_ATPCS ? 64 : STACK_BOUNDARY)
-
-#define FUNCTION_BOUNDARY 32
-
-/* The lowest bit is used to indicate Thumb-mode functions, so the
- vbit must go into the delta field of pointers to member
- functions. */
-#define TARGET_PTRMEMFUNC_VBIT_LOCATION ptrmemfunc_vbit_in_delta
-
-#define EMPTY_FIELD_BOUNDARY 32
-
-#define BIGGEST_ALIGNMENT (ARM_DOUBLEWORD_ALIGN ? DOUBLEWORD_ALIGNMENT : 32)
-
-/* XXX Blah -- this macro is used directly by libobjc. Since it
- supports no vector modes, cut out the complexity and fall back
- on BIGGEST_FIELD_ALIGNMENT. */
-#ifdef IN_TARGET_LIBS
-#define BIGGEST_FIELD_ALIGNMENT 64
-#endif
-
-/* Make strings word-aligned so strcpy from constants will be faster. */
-#define CONSTANT_ALIGNMENT_FACTOR (TARGET_THUMB || ! arm_tune_xscale ? 1 : 2)
-
-#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
- ((TREE_CODE (EXP) == STRING_CST \
- && (ALIGN) < BITS_PER_WORD * CONSTANT_ALIGNMENT_FACTOR) \
- ? BITS_PER_WORD * CONSTANT_ALIGNMENT_FACTOR : (ALIGN))
-
-/* Setting STRUCTURE_SIZE_BOUNDARY 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. For compatibility with the ARM SDK
- however the value should be left at 32. ARM SDT Reference Manual (ARM DUI
- 0020D) page 2-20 says "Structures are aligned on word boundaries".
- The AAPCS specifies a value of 8. */
-#define STRUCTURE_SIZE_BOUNDARY arm_structure_size_boundary
-extern int arm_structure_size_boundary;
-
-/* This is the value used to initialize arm_structure_size_boundary. If a
- particular arm target wants to change the default value it should change
- the definition of this macro, not STRUCTURE_SIZE_BOUNDARY. See netbsd.h
- for an example of this. */
-#ifndef DEFAULT_STRUCTURE_SIZE_BOUNDARY
-#define DEFAULT_STRUCTURE_SIZE_BOUNDARY 32
-#endif
-
-/* Nonzero if move instructions will actually fail to work
- when given unaligned data. */
-#define STRICT_ALIGNMENT 1
-
-/* wchar_t is unsigned under the AAPCS. */
-#ifndef WCHAR_TYPE
-#define WCHAR_TYPE (TARGET_AAPCS_BASED ? "unsigned int" : "int")
-
-#define WCHAR_TYPE_SIZE BITS_PER_WORD
-#endif
-
-#ifndef SIZE_TYPE
-#define SIZE_TYPE (TARGET_AAPCS_BASED ? "unsigned int" : "long unsigned int")
-#endif
-
-#ifndef PTRDIFF_TYPE
-#define PTRDIFF_TYPE (TARGET_AAPCS_BASED ? "int" : "long int")
-#endif
-
-/* AAPCS requires that structure alignment is affected by bitfields. */
-#ifndef PCC_BITFIELD_TYPE_MATTERS
-#define PCC_BITFIELD_TYPE_MATTERS TARGET_AAPCS_BASED
-#endif
-
-
-/* Standard register usage. */
-
-/* Register allocation in ARM Procedure Call Standard (as used on RISCiX):
- (S - saved over call).
-
- r0 * argument word/integer result
- r1-r3 argument word
-
- r4-r8 S register variable
- r9 S (rfp) register variable (real frame pointer)
-
- r10 F S (sl) stack limit (used by -mapcs-stack-check)
- r11 F S (fp) argument pointer
- r12 (ip) temp workspace
- r13 F S (sp) lower end of current stack frame
- r14 (lr) link address/workspace
- r15 F (pc) program counter
-
- f0 floating point result
- f1-f3 floating point scratch
-
- f4-f7 S floating point variable
-
- cc This is NOT a real register, but is used internally
- to represent things that use or set the condition
- codes.
- sfp This isn't either. It is used during rtl generation
- since the offset between the frame pointer and the
- auto's isn't known until after register allocation.
- afp Nor this, we only need this because of non-local
- goto. Without it fp appears to be used and the
- elimination code won't get rid of sfp. It tracks
- fp exactly at all times.
-
- *: See CONDITIONAL_REGISTER_USAGE */
-
-/*
- mvf0 Cirrus floating point result
- mvf1-mvf3 Cirrus floating point scratch
- mvf4-mvf15 S Cirrus floating point variable. */
-
-/* s0-s15 VFP scratch (aka d0-d7).
- s16-s31 S VFP variable (aka d8-d15).
- vfpcc Not a real register. Represents the VFP condition
- code flags. */
-
-/* The stack backtrace structure is as follows:
- fp points to here: | save code pointer | [fp]
- | return link value | [fp, #-4]
- | return sp value | [fp, #-8]
- | return fp value | [fp, #-12]
- [| saved r10 value |]
- [| saved r9 value |]
- [| saved r8 value |]
- [| saved r7 value |]
- [| saved r6 value |]
- [| saved r5 value |]
- [| saved r4 value |]
- [| saved r3 value |]
- [| saved r2 value |]
- [| saved r1 value |]
- [| saved r0 value |]
- [| saved f7 value |] three words
- [| saved f6 value |] three words
- [| saved f5 value |] three words
- [| saved f4 value |] three words
- r0-r3 are not normally saved in a C function. */
-
-/* 1 for registers that have pervasive standard uses
- and are not available for the register allocator. */
-#define FIXED_REGISTERS \
-{ \
- 0,0,0,0,0,0,0,0, \
- 0,0,0,0,0,1,0,1, \
- 0,0,0,0,0,0,0,0, \
- 1,1,1, \
- 1,1,1,1,1,1,1,1, \
- 1,1,1,1,1,1,1,1, \
- 1,1,1,1,1,1,1,1, \
- 1,1,1,1,1,1,1,1, \
- 1,1,1,1, \
- 1,1,1,1,1,1,1,1, \
- 1,1,1,1,1,1,1,1, \
- 1,1,1,1,1,1,1,1, \
- 1,1,1,1,1,1,1,1, \
- 1 \
-}
-
-/* 1 for registers not available across function calls.
- These must include the FIXED_REGISTERS and also any
- registers that can be used without being saved.
- The latter must include the registers where values are returned
- and the register where structure-value addresses are passed.
- Aside from that, you can include as many other registers as you like.
- The CC is not preserved over function calls on the ARM 6, so it is
- easier to assume this for all. SFP is preserved, since FP is. */
-#define CALL_USED_REGISTERS \
-{ \
- 1,1,1,1,0,0,0,0, \
- 0,0,0,0,1,1,1,1, \
- 1,1,1,1,0,0,0,0, \
- 1,1,1, \
- 1,1,1,1,1,1,1,1, \
- 1,1,1,1,1,1,1,1, \
- 1,1,1,1,1,1,1,1, \
- 1,1,1,1,1,1,1,1, \
- 1,1,1,1, \
- 1,1,1,1,1,1,1,1, \
- 1,1,1,1,1,1,1,1, \
- 1,1,1,1,1,1,1,1, \
- 1,1,1,1,1,1,1,1, \
- 1 \
-}
-
-#ifndef SUBTARGET_CONDITIONAL_REGISTER_USAGE
-#define SUBTARGET_CONDITIONAL_REGISTER_USAGE
-#endif
-
-#define CONDITIONAL_REGISTER_USAGE \
-{ \
- int regno; \
- \
- if (TARGET_SOFT_FLOAT || TARGET_THUMB || !TARGET_FPA) \
- { \
- for (regno = FIRST_FPA_REGNUM; \
- regno <= LAST_FPA_REGNUM; ++regno) \
- fixed_regs[regno] = call_used_regs[regno] = 1; \
- } \
- \
- if (TARGET_THUMB && optimize_size) \
- { \
- /* When optimizing for size, it's better not to use \
- the HI regs, because of the overhead of stacking \
- them. */ \
- for (regno = FIRST_HI_REGNUM; \
- regno <= LAST_HI_REGNUM; ++regno) \
- fixed_regs[regno] = call_used_regs[regno] = 1; \
- } \
- \
- /* The link register can be clobbered by any branch insn, \
- but we have no way to track that at present, so mark \
- it as unavailable. */ \
- if (TARGET_THUMB) \
- fixed_regs[LR_REGNUM] = call_used_regs[LR_REGNUM] = 1; \
- \
- if (TARGET_ARM && TARGET_HARD_FLOAT) \
- { \
- if (TARGET_MAVERICK) \
- { \
- for (regno = FIRST_FPA_REGNUM; \
- regno <= LAST_FPA_REGNUM; ++ regno) \
- fixed_regs[regno] = call_used_regs[regno] = 1; \
- for (regno = FIRST_CIRRUS_FP_REGNUM; \
- regno <= LAST_CIRRUS_FP_REGNUM; ++ regno) \
- { \
- fixed_regs[regno] = 0; \
- call_used_regs[regno] = regno < FIRST_CIRRUS_FP_REGNUM + 4; \
- } \
- } \
- if (TARGET_VFP) \
- { \
- for (regno = FIRST_VFP_REGNUM; \
- regno <= LAST_VFP_REGNUM; ++ regno) \
- { \
- fixed_regs[regno] = 0; \
- call_used_regs[regno] = regno < FIRST_VFP_REGNUM + 16; \
- } \
- } \
- } \
- \
- if (TARGET_REALLY_IWMMXT) \
- { \
- regno = FIRST_IWMMXT_GR_REGNUM; \
- /* The 2002/10/09 revision of the XScale ABI has wCG0 \
- and wCG1 as call-preserved registers. The 2002/11/21 \
- revision changed this so that all wCG registers are \
- scratch registers. */ \
- for (regno = FIRST_IWMMXT_GR_REGNUM; \
- regno <= LAST_IWMMXT_GR_REGNUM; ++ regno) \
- fixed_regs[regno] = 0; \
- /* The XScale ABI has wR0 - wR9 as scratch registers, \
- the rest as call-preserved registers. */ \
- for (regno = FIRST_IWMMXT_REGNUM; \
- regno <= LAST_IWMMXT_REGNUM; ++ regno) \
- { \
- fixed_regs[regno] = 0; \
- call_used_regs[regno] = regno < FIRST_IWMMXT_REGNUM + 10; \
- } \
- } \
- \
- if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM) \
- { \
- fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
- call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
- } \
- else if (TARGET_APCS_STACK) \
- { \
- fixed_regs[10] = 1; \
- call_used_regs[10] = 1; \
- } \
- /* -mcaller-super-interworking reserves r11 for calls to \
- _interwork_r11_call_via_rN(). Making the register global \
- is an easy way of ensuring that it remains valid for all \
- calls. */ \
- if (TARGET_APCS_FRAME || TARGET_CALLER_INTERWORKING \
- || TARGET_TPCS_FRAME || TARGET_TPCS_LEAF_FRAME) \
- { \
- fixed_regs[ARM_HARD_FRAME_POINTER_REGNUM] = 1; \
- call_used_regs[ARM_HARD_FRAME_POINTER_REGNUM] = 1; \
- if (TARGET_CALLER_INTERWORKING) \
- global_regs[ARM_HARD_FRAME_POINTER_REGNUM] = 1; \
- } \
- SUBTARGET_CONDITIONAL_REGISTER_USAGE \
-}
-
-/* These are a couple of extensions to the formats accepted
- by asm_fprintf:
- %@ prints out ASM_COMMENT_START
- %r prints out REGISTER_PREFIX reg_names[arg] */
-#define ASM_FPRINTF_EXTENSIONS(FILE, ARGS, P) \
- case '@': \
- fputs (ASM_COMMENT_START, FILE); \
- break; \
- \
- case 'r': \
- fputs (REGISTER_PREFIX, FILE); \
- fputs (reg_names [va_arg (ARGS, int)], FILE); \
- break;
-
-/* Round X up to the nearest word. */
-#define ROUND_UP_WORD(X) (((X) + 3) & ~3)
-
-/* Convert fron bytes to ints. */
-#define ARM_NUM_INTS(X) (((X) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
-/* The number of (integer) registers required to hold a quantity of type MODE.
- Also used for VFP registers. */
-#define ARM_NUM_REGS(MODE) \
- ARM_NUM_INTS (GET_MODE_SIZE (MODE))
-
-/* The number of (integer) registers required to hold a quantity of TYPE MODE. */
-#define ARM_NUM_REGS2(MODE, TYPE) \
- ARM_NUM_INTS ((MODE) == BLKmode ? \
- int_size_in_bytes (TYPE) : GET_MODE_SIZE (MODE))
-
-/* The number of (integer) argument register available. */
-#define NUM_ARG_REGS 4
-
-/* Return the register number of the N'th (integer) argument. */
-#define ARG_REGISTER(N) (N - 1)
-
-/* Specify the registers used for certain standard purposes.
- The values of these macros are register numbers. */
-
-/* The number of the last argument register. */
-#define LAST_ARG_REGNUM ARG_REGISTER (NUM_ARG_REGS)
-
-/* The numbers of the Thumb register ranges. */
-#define FIRST_LO_REGNUM 0
-#define LAST_LO_REGNUM 7
-#define FIRST_HI_REGNUM 8
-#define LAST_HI_REGNUM 11
-
-#ifndef TARGET_UNWIND_INFO
-/* We use sjlj exceptions for backwards compatibility. */
-#define MUST_USE_SJLJ_EXCEPTIONS 1
-#endif
-
-/* We can generate DWARF2 Unwind info, even though we don't use it. */
-#define DWARF2_UNWIND_INFO 1
-
-/* Use r0 and r1 to pass exception handling information. */
-#define EH_RETURN_DATA_REGNO(N) (((N) < 2) ? N : INVALID_REGNUM)
-
-/* The register that holds the return address in exception handlers. */
-#define ARM_EH_STACKADJ_REGNUM 2
-#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (SImode, ARM_EH_STACKADJ_REGNUM)
-
-/* The native (Norcroft) Pascal compiler for the ARM passes the static chain
- as an invisible last argument (possible since varargs don't exist in
- Pascal), so the following is not true. */
-#define STATIC_CHAIN_REGNUM (TARGET_ARM ? 12 : 9)
-
-/* Define this to be where the real frame pointer is if it is not possible to
- work out the offset between the frame pointer and the automatic variables
- until after register allocation has taken place. FRAME_POINTER_REGNUM
- should point to a special register that we will make sure is eliminated.
-
- For the Thumb we have another problem. The TPCS defines the frame pointer
- as r11, and GCC believes that it is always possible to use the frame pointer
- as base register for addressing purposes. (See comments in
- find_reloads_address()). But - the Thumb does not allow high registers,
- including r11, to be used as base address registers. Hence our problem.
-
- The solution used here, and in the old thumb port is to use r7 instead of
- r11 as the hard frame pointer and to have special code to generate
- backtrace structures on the stack (if required to do so via a command line
- option) using r11. This is the only 'user visible' use of r11 as a frame
- pointer. */
-#define ARM_HARD_FRAME_POINTER_REGNUM 11
-#define THUMB_HARD_FRAME_POINTER_REGNUM 7
-
-#define HARD_FRAME_POINTER_REGNUM \
- (TARGET_ARM \
- ? ARM_HARD_FRAME_POINTER_REGNUM \
- : THUMB_HARD_FRAME_POINTER_REGNUM)
-
-#define FP_REGNUM HARD_FRAME_POINTER_REGNUM
-
-/* Register to use for pushing function arguments. */
-#define STACK_POINTER_REGNUM SP_REGNUM
-
-/* ARM floating pointer registers. */
-#define FIRST_FPA_REGNUM 16
-#define LAST_FPA_REGNUM 23
-#define IS_FPA_REGNUM(REGNUM) \
- (((REGNUM) >= FIRST_FPA_REGNUM) && ((REGNUM) <= LAST_FPA_REGNUM))
-
-#define FIRST_IWMMXT_GR_REGNUM 43
-#define LAST_IWMMXT_GR_REGNUM 46
-#define FIRST_IWMMXT_REGNUM 47
-#define LAST_IWMMXT_REGNUM 62
-#define IS_IWMMXT_REGNUM(REGNUM) \
- (((REGNUM) >= FIRST_IWMMXT_REGNUM) && ((REGNUM) <= LAST_IWMMXT_REGNUM))
-#define IS_IWMMXT_GR_REGNUM(REGNUM) \
- (((REGNUM) >= FIRST_IWMMXT_GR_REGNUM) && ((REGNUM) <= LAST_IWMMXT_GR_REGNUM))
-
-/* Base register for access to local variables of the function. */
-#define FRAME_POINTER_REGNUM 25
-
-/* Base register for access to arguments of the function. */
-#define ARG_POINTER_REGNUM 26
-
-#define FIRST_CIRRUS_FP_REGNUM 27
-#define LAST_CIRRUS_FP_REGNUM 42
-#define IS_CIRRUS_REGNUM(REGNUM) \
- (((REGNUM) >= FIRST_CIRRUS_FP_REGNUM) && ((REGNUM) <= LAST_CIRRUS_FP_REGNUM))
-
-#define FIRST_VFP_REGNUM 63
-#define LAST_VFP_REGNUM 94
-#define IS_VFP_REGNUM(REGNUM) \
- (((REGNUM) >= FIRST_VFP_REGNUM) && ((REGNUM) <= LAST_VFP_REGNUM))
-
-/* The number of hard registers is 16 ARM + 8 FPA + 1 CC + 1 SFP + 1 AFP. */
-/* + 16 Cirrus registers take us up to 43. */
-/* Intel Wireless MMX Technology registers add 16 + 4 more. */
-/* VFP adds 32 + 1 more. */
-#define FIRST_PSEUDO_REGISTER 96
-
-#define DBX_REGISTER_NUMBER(REGNO) arm_dbx_register_number (REGNO)
-
-/* Value should be nonzero if functions must have frame pointers.
- Zero means the frame pointer need not be set up (and parms may be accessed
- via the stack pointer) in functions that seem suitable.
- If we have to have a frame pointer we might as well make use of it.
- APCS says that the frame pointer does not need to be pushed in leaf
- functions, or simple tail call functions. */
-
-#ifndef SUBTARGET_FRAME_POINTER_REQUIRED
-#define SUBTARGET_FRAME_POINTER_REQUIRED 0
-#endif
-
-#define FRAME_POINTER_REQUIRED \
- (current_function_has_nonlocal_label \
- || SUBTARGET_FRAME_POINTER_REQUIRED \
- || (TARGET_ARM && TARGET_APCS_FRAME && ! leaf_function_p ()))
-
-/* Return number of consecutive hard regs needed starting at reg REGNO
- to hold something of mode MODE.
- This is ordinarily the length in words of a value of mode MODE
- but can be less for certain modes in special long registers.
-
- On the ARM regs are UNITS_PER_WORD bits wide; FPA regs can hold any FP
- mode. */
-#define HARD_REGNO_NREGS(REGNO, MODE) \
- ((TARGET_ARM \
- && REGNO >= FIRST_FPA_REGNUM \
- && REGNO != FRAME_POINTER_REGNUM \
- && REGNO != ARG_POINTER_REGNUM) \
- && !IS_VFP_REGNUM (REGNO) \
- ? 1 : ARM_NUM_REGS (MODE))
-
-/* Return true if REGNO is suitable for holding a quantity of type MODE. */
-#define HARD_REGNO_MODE_OK(REGNO, MODE) \
- arm_hard_regno_mode_ok ((REGNO), (MODE))
-
-/* Value is 1 if it is a good idea to tie two pseudo registers
- when one has mode MODE1 and one has mode MODE2.
- If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
- for any hard reg, then this must be 0 for correct output. */
-#define MODES_TIEABLE_P(MODE1, MODE2) \
- (GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2))
-
-#define VALID_IWMMXT_REG_MODE(MODE) \
- (arm_vector_mode_supported_p (MODE) || (MODE) == DImode)
-
-/* The order in which register should be allocated. It is good to use ip
- since no saving is required (though calls clobber it) and it never contains
- function parameters. It is quite good to use lr since other calls may
- clobber it anyway. Allocate r0 through r3 in reverse order since r3 is
- least likely to contain a function parameter; in addition results are
- returned in r0. */
-
-#define REG_ALLOC_ORDER \
-{ \
- 3, 2, 1, 0, 12, 14, 4, 5, \
- 6, 7, 8, 10, 9, 11, 13, 15, \
- 16, 17, 18, 19, 20, 21, 22, 23, \
- 27, 28, 29, 30, 31, 32, 33, 34, \
- 35, 36, 37, 38, 39, 40, 41, 42, \
- 43, 44, 45, 46, 47, 48, 49, 50, \
- 51, 52, 53, 54, 55, 56, 57, 58, \
- 59, 60, 61, 62, \
- 24, 25, 26, \
- 78, 77, 76, 75, 74, 73, 72, 71, \
- 70, 69, 68, 67, 66, 65, 64, 63, \
- 79, 80, 81, 82, 83, 84, 85, 86, \
- 87, 88, 89, 90, 91, 92, 93, 94, \
- 95 \
-}
-
-/* Interrupt functions can only use registers that have already been
- saved by the prologue, even if they would normally be
- call-clobbered. */
-#define HARD_REGNO_RENAME_OK(SRC, DST) \
- (! IS_INTERRUPT (cfun->machine->func_type) || \
- regs_ever_live[DST])
-
-/* Register and constant classes. */
-
-/* Register classes: used to be simple, just all ARM regs or all FPA regs
- Now that the Thumb is involved it has become more complicated. */
-enum reg_class
-{
- NO_REGS,
- FPA_REGS,
- CIRRUS_REGS,
- VFP_REGS,
- IWMMXT_GR_REGS,
- IWMMXT_REGS,
- LO_REGS,
- STACK_REG,
- BASE_REGS,
- HI_REGS,
- CC_REG,
- VFPCC_REG,
- GENERAL_REGS,
- ALL_REGS,
- LIM_REG_CLASSES
-};
-
-#define N_REG_CLASSES (int) LIM_REG_CLASSES
-
-/* Give names of register classes as strings for dump file. */
-#define REG_CLASS_NAMES \
-{ \
- "NO_REGS", \
- "FPA_REGS", \
- "CIRRUS_REGS", \
- "VFP_REGS", \
- "IWMMXT_GR_REGS", \
- "IWMMXT_REGS", \
- "LO_REGS", \
- "STACK_REG", \
- "BASE_REGS", \
- "HI_REGS", \
- "CC_REG", \
- "VFPCC_REG", \
- "GENERAL_REGS", \
- "ALL_REGS", \
-}
-
-/* Define which registers fit in which classes.
- This is an initializer for a vector of HARD_REG_SET
- of length N_REG_CLASSES. */
-#define REG_CLASS_CONTENTS \
-{ \
- { 0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS */ \
- { 0x00FF0000, 0x00000000, 0x00000000 }, /* FPA_REGS */ \
- { 0xF8000000, 0x000007FF, 0x00000000 }, /* CIRRUS_REGS */ \
- { 0x00000000, 0x80000000, 0x7FFFFFFF }, /* VFP_REGS */ \
- { 0x00000000, 0x00007800, 0x00000000 }, /* IWMMXT_GR_REGS */ \
- { 0x00000000, 0x7FFF8000, 0x00000000 }, /* IWMMXT_REGS */ \
- { 0x000000FF, 0x00000000, 0x00000000 }, /* LO_REGS */ \
- { 0x00002000, 0x00000000, 0x00000000 }, /* STACK_REG */ \
- { 0x000020FF, 0x00000000, 0x00000000 }, /* BASE_REGS */ \
- { 0x0000FF00, 0x00000000, 0x00000000 }, /* HI_REGS */ \
- { 0x01000000, 0x00000000, 0x00000000 }, /* CC_REG */ \
- { 0x00000000, 0x00000000, 0x80000000 }, /* VFPCC_REG */ \
- { 0x0200FFFF, 0x00000000, 0x00000000 }, /* GENERAL_REGS */ \
- { 0xFAFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF } /* ALL_REGS */ \
-}
-
-/* The same information, inverted:
- Return the class number of the smallest class containing
- reg number REGNO. This could be a conditional expression
- or could index an array. */
-#define REGNO_REG_CLASS(REGNO) arm_regno_class (REGNO)
-
-/* FPA registers can't do subreg as all values are reformatted to internal
- precision. VFP registers may only be accessed in the mode they
- were set. */
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
- (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
- ? reg_classes_intersect_p (FPA_REGS, (CLASS)) \
- || reg_classes_intersect_p (VFP_REGS, (CLASS)) \
- : 0)
-
-/* We need to define this for LO_REGS on thumb. Otherwise we can end up
- using r0-r4 for function arguments, r7 for the stack frame and don't
- have enough left over to do doubleword arithmetic. */
-#define CLASS_LIKELY_SPILLED_P(CLASS) \
- ((TARGET_THUMB && (CLASS) == LO_REGS) \
- || (CLASS) == CC_REG)
-
-/* The class value for index registers, and the one for base regs. */
-#define INDEX_REG_CLASS (TARGET_THUMB ? LO_REGS : GENERAL_REGS)
-#define BASE_REG_CLASS (TARGET_THUMB ? LO_REGS : GENERAL_REGS)
-
-/* For the Thumb the high registers cannot be used as base registers
- when addressing quantities in QI or HI mode; if we don't know the
- mode, then we must be conservative. */
-#define MODE_BASE_REG_CLASS(MODE) \
- (TARGET_ARM ? GENERAL_REGS : \
- (((MODE) == SImode) ? BASE_REGS : LO_REGS))
-
-/* For Thumb we can not support SP+reg addressing, so we return LO_REGS
- instead of BASE_REGS. */
-#define MODE_BASE_REG_REG_CLASS(MODE) BASE_REG_CLASS
-
-/* 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 TARGET_THUMB
-
-/* Given an rtx X being reloaded into a reg required to be
- in class CLASS, return the class of reg to actually use.
- In general this is just CLASS, but for the Thumb we prefer
- a LO_REGS class or a subset. */
-#define PREFERRED_RELOAD_CLASS(X, CLASS) \
- (TARGET_ARM ? (CLASS) : \
- ((CLASS) == BASE_REGS ? (CLASS) : LO_REGS))
-
-/* Must leave BASE_REGS reloads alone */
-#define THUMB_SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \
- ((CLASS) != LO_REGS && (CLASS) != BASE_REGS \
- ? ((true_regnum (X) == -1 ? LO_REGS \
- : (true_regnum (X) + HARD_REGNO_NREGS (0, MODE) > 8) ? LO_REGS \
- : NO_REGS)) \
- : NO_REGS)
-
-#define THUMB_SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \
- ((CLASS) != LO_REGS && (CLASS) != BASE_REGS \
- ? ((true_regnum (X) == -1 ? LO_REGS \
- : (true_regnum (X) + HARD_REGNO_NREGS (0, MODE) > 8) ? LO_REGS \
- : NO_REGS)) \
- : NO_REGS)
-
-/* Return the register class of a scratch register needed to copy IN into
- or out of a register in CLASS in MODE. If it can be done directly,
- NO_REGS is returned. */
-#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \
- /* Restrict which direct reloads are allowed for VFP/iWMMXt regs. */ \
- ((TARGET_VFP && TARGET_HARD_FLOAT \
- && (CLASS) == VFP_REGS) \
- ? coproc_secondary_reload_class (MODE, X, FALSE) \
- : (TARGET_IWMMXT && (CLASS) == IWMMXT_REGS) \
- ? coproc_secondary_reload_class (MODE, X, TRUE) \
- : TARGET_ARM \
- ? (((MODE) == HImode && ! arm_arch4 && true_regnum (X) == -1) \
- ? GENERAL_REGS : NO_REGS) \
- : THUMB_SECONDARY_OUTPUT_RELOAD_CLASS (CLASS, MODE, X))
-
-/* If we need to load shorts byte-at-a-time, then we need a scratch. */
-#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \
- /* Restrict which direct reloads are allowed for VFP/iWMMXt regs. */ \
- ((TARGET_VFP && TARGET_HARD_FLOAT \
- && (CLASS) == VFP_REGS) \
- ? coproc_secondary_reload_class (MODE, X, FALSE) : \
- (TARGET_IWMMXT && (CLASS) == IWMMXT_REGS) ? \
- coproc_secondary_reload_class (MODE, X, TRUE) : \
- /* Cannot load constants into Cirrus registers. */ \
- (TARGET_MAVERICK && TARGET_HARD_FLOAT \
- && (CLASS) == CIRRUS_REGS \
- && (CONSTANT_P (X) || GET_CODE (X) == SYMBOL_REF)) \
- ? GENERAL_REGS : \
- (TARGET_ARM ? \
- (((CLASS) == IWMMXT_REGS || (CLASS) == IWMMXT_GR_REGS) \
- && CONSTANT_P (X)) \
- ? GENERAL_REGS : \
- (((MODE) == HImode && ! arm_arch4 \
- && (GET_CODE (X) == MEM \
- || ((GET_CODE (X) == REG || GET_CODE (X) == SUBREG) \
- && true_regnum (X) == -1))) \
- ? GENERAL_REGS : NO_REGS) \
- : THUMB_SECONDARY_INPUT_RELOAD_CLASS (CLASS, MODE, X)))
-
-/* Try a machine-dependent way of reloading an illegitimate address
- operand. If we find one, push the reload and jump to WIN. This
- macro is used in only one place: `find_reloads_address' in reload.c.
-
- For the ARM, we wish to handle large displacements off a base
- register by splitting the addend across a MOV and the mem insn.
- This can cut the number of reloads needed. */
-#define ARM_LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND, WIN) \
- do \
- { \
- if (GET_CODE (X) == PLUS \
- && GET_CODE (XEXP (X, 0)) == REG \
- && REGNO (XEXP (X, 0)) < FIRST_PSEUDO_REGISTER \
- && REG_MODE_OK_FOR_BASE_P (XEXP (X, 0), MODE) \
- && GET_CODE (XEXP (X, 1)) == CONST_INT) \
- { \
- HOST_WIDE_INT val = INTVAL (XEXP (X, 1)); \
- HOST_WIDE_INT low, high; \
- \
- if (MODE == DImode || (MODE == DFmode && TARGET_SOFT_FLOAT)) \
- low = ((val & 0xf) ^ 0x8) - 0x8; \
- else if (TARGET_MAVERICK && TARGET_HARD_FLOAT) \
- /* Need to be careful, -256 is not a valid offset. */ \
- low = val >= 0 ? (val & 0xff) : -((-val) & 0xff); \
- else if (MODE == SImode \
- || (MODE == SFmode && TARGET_SOFT_FLOAT) \
- || ((MODE == HImode || MODE == QImode) && ! arm_arch4)) \
- /* Need to be careful, -4096 is not a valid offset. */ \
- low = val >= 0 ? (val & 0xfff) : -((-val) & 0xfff); \
- else if ((MODE == HImode || MODE == QImode) && arm_arch4) \
- /* Need to be careful, -256 is not a valid offset. */ \
- low = val >= 0 ? (val & 0xff) : -((-val) & 0xff); \
- else if (GET_MODE_CLASS (MODE) == MODE_FLOAT \
- && TARGET_HARD_FLOAT && TARGET_FPA) \
- /* Need to be careful, -1024 is not a valid offset. */ \
- low = val >= 0 ? (val & 0x3ff) : -((-val) & 0x3ff); \
- else \
- break; \
- \
- high = ((((val - low) & (unsigned HOST_WIDE_INT) 0xffffffff) \
- ^ (unsigned HOST_WIDE_INT) 0x80000000) \
- - (unsigned HOST_WIDE_INT) 0x80000000); \
- /* Check for overflow or zero */ \
- if (low == 0 || high == 0 || (high + low != val)) \
- break; \
- \
- /* Reload the high part into a base reg; leave the low part \
- in the mem. */ \
- X = gen_rtx_PLUS (GET_MODE (X), \
- gen_rtx_PLUS (GET_MODE (X), XEXP (X, 0), \
- GEN_INT (high)), \
- GEN_INT (low)); \
- push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL, \
- MODE_BASE_REG_CLASS (MODE), GET_MODE (X), \
- VOIDmode, 0, 0, OPNUM, TYPE); \
- goto WIN; \
- } \
- } \
- while (0)
-
-/* XXX 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 THUMB_LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND_L, WIN) \
-do { \
- rtx new_x = thumb_legitimize_reload_address (&X, MODE, OPNUM, TYPE, IND_L); \
- if (new_x) \
- { \
- X = new_x; \
- goto WIN; \
- } \
-} while (0)
-
-#define LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND_LEVELS, WIN) \
- if (TARGET_ARM) \
- ARM_LEGITIMIZE_RELOAD_ADDRESS (X, MODE, OPNUM, TYPE, IND_LEVELS, WIN); \
- else \
- THUMB_LEGITIMIZE_RELOAD_ADDRESS (X, MODE, OPNUM, TYPE, IND_LEVELS, WIN)
-
-/* Return the maximum number of consecutive registers
- needed to represent mode MODE in a register of class CLASS.
- ARM regs are UNITS_PER_WORD bits while FPA regs can hold any FP mode */
-#define CLASS_MAX_NREGS(CLASS, MODE) \
- (((CLASS) == FPA_REGS || (CLASS) == CIRRUS_REGS) ? 1 : ARM_NUM_REGS (MODE))
-
-/* If defined, gives a class of registers that cannot be used as the
- operand of a SUBREG that changes the mode of the object illegally. */
-
-/* Moves between FPA_REGS and GENERAL_REGS are two memory insns. */
-#define REGISTER_MOVE_COST(MODE, FROM, TO) \
- (TARGET_ARM ? \
- ((FROM) == FPA_REGS && (TO) != FPA_REGS ? 20 : \
- (FROM) != FPA_REGS && (TO) == FPA_REGS ? 20 : \
- (FROM) == VFP_REGS && (TO) != VFP_REGS ? 10 : \
- (FROM) != VFP_REGS && (TO) == VFP_REGS ? 10 : \
- (FROM) == IWMMXT_REGS && (TO) != IWMMXT_REGS ? 4 : \
- (FROM) != IWMMXT_REGS && (TO) == IWMMXT_REGS ? 4 : \
- (FROM) == IWMMXT_GR_REGS || (TO) == IWMMXT_GR_REGS ? 20 : \
- (FROM) == CIRRUS_REGS && (TO) != CIRRUS_REGS ? 20 : \
- (FROM) != CIRRUS_REGS && (TO) == CIRRUS_REGS ? 20 : \
- 2) \
- : \
- ((FROM) == HI_REGS || (TO) == HI_REGS) ? 4 : 2)
-
-/* Stack layout; function entry, exit and calling. */
-
-/* Define this if pushing a word on the stack
- makes the stack pointer a smaller address. */
-#define STACK_GROWS_DOWNWARD 1
-
-/* Define this to nonzero if the nominal address of the stack frame
- is at the high-address end of the local variables;
- that is, each additional local variable allocated
- goes at a more negative offset in the frame. */
-#define FRAME_GROWS_DOWNWARD 1
-
-/* The amount of scratch space needed by _interwork_{r7,r11}_call_via_rN().
- When present, it is one word in size, and sits at the top of the frame,
- between the soft frame pointer and either r7 or r11.
-
- We only need _interwork_rM_call_via_rN() for -mcaller-super-interworking,
- and only then if some outgoing arguments are passed on the stack. It would
- be tempting to also check whether the stack arguments are passed by indirect
- calls, but there seems to be no reason in principle why a post-reload pass
- couldn't convert a direct call into an indirect one. */
-#define CALLER_INTERWORKING_SLOT_SIZE \
- (TARGET_CALLER_INTERWORKING \
- && current_function_outgoing_args_size != 0 \
- ? UNITS_PER_WORD : 0)
-
-/* Offset within stack frame to start allocating local variables at.
- If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
- first local allocated. Otherwise, it is the offset to the BEGINNING
- of the first local allocated. */
-#define STARTING_FRAME_OFFSET 0
-
-/* If we generate an insn to push BYTES bytes,
- this says how many the stack pointer really advances by. */
-/* The push insns do not do this rounding implicitly.
- So don't define this. */
-/* #define PUSH_ROUNDING(NPUSHED) ROUND_UP_WORD (NPUSHED) */
-
-/* Define this if the maximum size of all the outgoing args is to be
- accumulated and pushed during the prologue. The amount can be
- found in the variable current_function_outgoing_args_size. */
-#define ACCUMULATE_OUTGOING_ARGS 1
-
-/* Offset of first parameter from the argument pointer register value. */
-#define FIRST_PARM_OFFSET(FNDECL) (TARGET_ARM ? 4 : 0)
-
-/* Value is the number of byte of arguments automatically
- popped when returning from a subroutine call.
- FUNDECL is the declaration node of the function (as a tree),
- FUNTYPE is the data type of the function (as a tree),
- or for a library call it is an identifier node for the subroutine name.
- SIZE is the number of bytes of arguments passed on the stack.
-
- On the ARM, the caller does not pop any of its arguments that were passed
- on the stack. */
-#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, SIZE) 0
-
-/* Define how to find the value returned by a library function
- assuming the value has mode MODE. */
-#define LIBCALL_VALUE(MODE) \
- (TARGET_ARM && TARGET_HARD_FLOAT_ABI && TARGET_FPA \
- && GET_MODE_CLASS (MODE) == MODE_FLOAT \
- ? gen_rtx_REG (MODE, FIRST_FPA_REGNUM) \
- : TARGET_ARM && TARGET_HARD_FLOAT_ABI && TARGET_MAVERICK \
- && GET_MODE_CLASS (MODE) == MODE_FLOAT \
- ? gen_rtx_REG (MODE, FIRST_CIRRUS_FP_REGNUM) \
- : TARGET_IWMMXT_ABI && arm_vector_mode_supported_p (MODE) \
- ? gen_rtx_REG (MODE, FIRST_IWMMXT_REGNUM) \
- : gen_rtx_REG (MODE, ARG_REGISTER (1)))
-
-/* Define how to find the value returned by a function.
- VALTYPE is the data type of the value (as a tree).
- If the precise function being called is known, FUNC is its FUNCTION_DECL;
- otherwise, FUNC is 0. */
-#define FUNCTION_VALUE(VALTYPE, FUNC) \
- arm_function_value (VALTYPE, FUNC);
-
-/* 1 if N is a possible register number for a function value.
- On the ARM, only r0 and f0 can return results. */
-/* On a Cirrus chip, mvf0 can return results. */
-#define FUNCTION_VALUE_REGNO_P(REGNO) \
- ((REGNO) == ARG_REGISTER (1) \
- || (TARGET_ARM && ((REGNO) == FIRST_CIRRUS_FP_REGNUM) \
- && TARGET_HARD_FLOAT_ABI && TARGET_MAVERICK) \
- || ((REGNO) == FIRST_IWMMXT_REGNUM && TARGET_IWMMXT_ABI) \
- || (TARGET_ARM && ((REGNO) == FIRST_FPA_REGNUM) \
- && TARGET_HARD_FLOAT_ABI && TARGET_FPA))
-
-/* Amount of memory needed for an untyped call to save all possible return
- registers. */
-#define APPLY_RESULT_SIZE arm_apply_result_size()
-
-/* 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) arm_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
-
-/* Flags for the call/call_value rtl operations set up by function_arg. */
-#define CALL_NORMAL 0x00000000 /* No special processing. */
-#define CALL_LONG 0x00000001 /* Always call indirect. */
-#define CALL_SHORT 0x00000002 /* Never call indirect. */
-
-/* These bits describe the different types of function supported
- by the ARM backend. They are exclusive. i.e. a function cannot be both a
- normal function and an interworked function, for example. Knowing the
- type of a function is important for determining its prologue and
- epilogue sequences.
- Note value 7 is currently unassigned. Also note that the interrupt
- function types all have bit 2 set, so that they can be tested for easily.
- Note that 0 is deliberately chosen for ARM_FT_UNKNOWN so that when the
- machine_function structure is initialized (to zero) func_type will
- default to unknown. This will force the first use of arm_current_func_type
- to call arm_compute_func_type. */
-#define ARM_FT_UNKNOWN 0 /* Type has not yet been determined. */
-#define ARM_FT_NORMAL 1 /* Your normal, straightforward function. */
-#define ARM_FT_INTERWORKED 2 /* A function that supports interworking. */
-#define ARM_FT_ISR 4 /* An interrupt service routine. */
-#define ARM_FT_FIQ 5 /* A fast interrupt service routine. */
-#define ARM_FT_EXCEPTION 6 /* An ARM exception handler (subcase of ISR). */
-
-#define ARM_FT_TYPE_MASK ((1 << 3) - 1)
-
-/* In addition functions can have several type modifiers,
- outlined by these bit masks: */
-#define ARM_FT_INTERRUPT (1 << 2) /* Note overlap with FT_ISR and above. */
-#define ARM_FT_NAKED (1 << 3) /* No prologue or epilogue. */
-#define ARM_FT_VOLATILE (1 << 4) /* Does not return. */
-#define ARM_FT_NESTED (1 << 5) /* Embedded inside another func. */
-
-/* Some macros to test these flags. */
-#define ARM_FUNC_TYPE(t) (t & ARM_FT_TYPE_MASK)
-#define IS_INTERRUPT(t) (t & ARM_FT_INTERRUPT)
-#define IS_VOLATILE(t) (t & ARM_FT_VOLATILE)
-#define IS_NAKED(t) (t & ARM_FT_NAKED)
-#define IS_NESTED(t) (t & ARM_FT_NESTED)
-
-
-/* Structure used to hold the function stack frame layout. Offsets are
- relative to the stack pointer on function entry. Positive offsets are
- in the direction of stack growth.
- Only soft_frame is used in thumb mode. */
-
-typedef struct arm_stack_offsets GTY(())
-{
- int saved_args; /* ARG_POINTER_REGNUM. */
- int frame; /* ARM_HARD_FRAME_POINTER_REGNUM. */
- int saved_regs;
- int soft_frame; /* FRAME_POINTER_REGNUM. */
- int locals_base; /* THUMB_HARD_FRAME_POINTER_REGNUM. */
- int outgoing_args; /* STACK_POINTER_REGNUM. */
-}
-arm_stack_offsets;
-
-/* A C structure for machine-specific, per-function data.
- This is added to the cfun structure. */
-typedef struct machine_function GTY(())
-{
- /* Additional stack adjustment in __builtin_eh_throw. */
- rtx eh_epilogue_sp_ofs;
- /* Records if LR has to be saved for far jumps. */
- int far_jump_used;
- /* Records if ARG_POINTER was ever live. */
- int arg_pointer_live;
- /* Records if the save of LR has been eliminated. */
- int lr_save_eliminated;
- /* The size of the stack frame. Only valid after reload. */
- arm_stack_offsets stack_offsets;
- /* Records the type of the current function. */
- unsigned long func_type;
- /* Record if the function has a variable argument list. */
- int uses_anonymous_args;
- /* Records if sibcalls are blocked because an argument
- register is needed to preserve stack alignment. */
- int sibcall_blocked;
- /* The PIC register for this function. This might be a pseudo. */
- rtx pic_reg;
- /* Labels for per-function Thumb call-via stubs. One per potential calling
- register. We can never call via LR or PC. We can call via SP if a
- trampoline happens to be on the top of the stack. */
- rtx call_via[14];
-}
-machine_function;
-
-/* As in the machine_function, a global set of call-via labels, for code
- that is in text_section. */
-extern GTY(()) rtx thumb_call_via_label[14];
-
-/* A C type for declaring a variable that is used as the first argument of
- `FUNCTION_ARG' and other related values. For some target machines, the
- type `int' suffices and can hold the number of bytes of argument so far. */
-typedef struct
-{
- /* This is the number of registers of arguments scanned so far. */
- int nregs;
- /* This is the number of iWMMXt register arguments scanned so far. */
- int iwmmxt_nregs;
- int named_count;
- int nargs;
- /* One of CALL_NORMAL, CALL_LONG or CALL_SHORT. */
- int call_cookie;
- int can_split;
-} CUMULATIVE_ARGS;
-
-/* Define where to put the arguments to a function.
- Value is zero to push the argument on the stack,
- or a hard register in which to store the argument.
-
- MODE is the argument's machine mode.
- TYPE is the data type of the argument (as a tree).
- This is null for libcalls where that information may
- not be available.
- CUM is a variable of type CUMULATIVE_ARGS which gives info about
- the preceding args and about the function being called.
- NAMED is nonzero if this argument is a named parameter
- (otherwise it is an extra parameter matching an ellipsis).
-
- On the ARM, normally the first 16 bytes are passed in registers r0-r3; all
- other arguments are passed on the stack. If (NAMED == 0) (which happens
- only in assign_parms, since TARGET_SETUP_INCOMING_VARARGS is
- defined), say it is passed in the stack (function_prologue will
- indeed make it pass in the stack if necessary). */
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- arm_function_arg (&(CUM), (MODE), (TYPE), (NAMED))
-
-#define FUNCTION_ARG_PADDING(MODE, TYPE) \
- (arm_pad_arg_upward (MODE, TYPE) ? upward : downward)
-
-#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
- (arm_pad_reg_upward (MODE, TYPE, FIRST) ? upward : downward)
-
-/* For AAPCS, padding should never be below the argument. For other ABIs,
- * mimic the default. */
-#define PAD_VARARGS_DOWN \
- ((TARGET_AAPCS_BASED) ? 0 : BYTES_BIG_ENDIAN)
-
-/* Initialize a variable CUM of type CUMULATIVE_ARGS
- for a call to a function whose data type is FNTYPE.
- For a library call, FNTYPE is 0.
- On the ARM, the offset starts at 0. */
-#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
- arm_init_cumulative_args (&(CUM), (FNTYPE), (LIBNAME), (FNDECL))
-
-/* Update the data in CUM to advance over an argument
- of mode MODE and data type TYPE.
- (TYPE is null for libcalls where that information may not be available.) */
-#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
- (CUM).nargs += 1; \
- if (arm_vector_mode_supported_p (MODE) \
- && (CUM).named_count > (CUM).nargs) \
- (CUM).iwmmxt_nregs += 1; \
- else \
- (CUM).nregs += ARM_NUM_REGS2 (MODE, TYPE)
-
-/* If defined, a C expression that gives the alignment boundary, in bits, of an
- argument with the specified mode and type. If it is not defined,
- `PARM_BOUNDARY' is used for all arguments. */
-#define FUNCTION_ARG_BOUNDARY(MODE,TYPE) \
- ((ARM_DOUBLEWORD_ALIGN && arm_needs_doubleword_align (MODE, TYPE)) \
- ? DOUBLEWORD_ALIGNMENT \
- : PARM_BOUNDARY )
-
-/* 1 if N is a possible register number for function argument passing.
- On the ARM, r0-r3 are used to pass args. */
-#define FUNCTION_ARG_REGNO_P(REGNO) \
- (IN_RANGE ((REGNO), 0, 3) \
- || (TARGET_IWMMXT_ABI \
- && IN_RANGE ((REGNO), FIRST_IWMMXT_REGNUM, FIRST_IWMMXT_REGNUM + 9)))
-
-
-/* If your target environment doesn't prefix user functions with an
- underscore, you may wish to re-define this to prevent any conflicts.
- e.g. AOF may prefix mcount with an underscore. */
-#ifndef ARM_MCOUNT_NAME
-#define ARM_MCOUNT_NAME "*mcount"
-#endif
-
-/* Call the function profiler with a given profile label. The Acorn
- compiler puts this BEFORE the prolog but gcc puts it afterwards.
- On the ARM the full profile code will look like:
- .data
- LP1
- .word 0
- .text
- mov ip, lr
- bl mcount
- .word LP1
-
- profile_function() in final.c outputs the .data section, FUNCTION_PROFILER
- will output the .text section.
-
- The ``mov ip,lr'' seems like a good idea to stick with cc convention.
- ``prof'' doesn't seem to mind about this!
-
- Note - this version of the code is designed to work in both ARM and
- Thumb modes. */
-#ifndef ARM_FUNCTION_PROFILER
-#define ARM_FUNCTION_PROFILER(STREAM, LABELNO) \
-{ \
- char temp[20]; \
- rtx sym; \
- \
- asm_fprintf (STREAM, "\tmov\t%r, %r\n\tbl\t", \
- IP_REGNUM, LR_REGNUM); \
- assemble_name (STREAM, ARM_MCOUNT_NAME); \
- fputc ('\n', STREAM); \
- ASM_GENERATE_INTERNAL_LABEL (temp, "LP", LABELNO); \
- sym = gen_rtx_SYMBOL_REF (Pmode, temp); \
- assemble_aligned_integer (UNITS_PER_WORD, sym); \
-}
-#endif
-
-#ifdef THUMB_FUNCTION_PROFILER
-#define FUNCTION_PROFILER(STREAM, LABELNO) \
- if (TARGET_ARM) \
- ARM_FUNCTION_PROFILER (STREAM, LABELNO) \
- else \
- THUMB_FUNCTION_PROFILER (STREAM, LABELNO)
-#else
-#define FUNCTION_PROFILER(STREAM, LABELNO) \
- ARM_FUNCTION_PROFILER (STREAM, LABELNO)
-#endif
-
-/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
- the stack pointer does not matter. The value is tested only in
- functions that have frame pointers.
- No definition is equivalent to always zero.
-
- On the ARM, the function epilogue recovers the stack pointer from the
- frame. */
-#define EXIT_IGNORE_STACK 1
-
-#define EPILOGUE_USES(REGNO) (reload_completed && (REGNO) == LR_REGNUM)
-
-/* Determine if the epilogue should be output as RTL.
- You should override this if you define FUNCTION_EXTRA_EPILOGUE. */
-#define USE_RETURN_INSN(ISCOND) \
- (TARGET_ARM ? use_return_insn (ISCOND, NULL) : 0)
-
-/* Definitions for register eliminations.
-
- This is an array of structures. Each structure initializes one pair
- of eliminable registers. The "from" register number is given first,
- followed by "to". Eliminations of the same "from" register are listed
- in order of preference.
-
- We have two registers that can be eliminated on the ARM. First, the
- arg pointer register can often be eliminated in favor of the stack
- pointer register. Secondly, the pseudo frame pointer register can always
- be eliminated; it is replaced with either the stack or the real frame
- pointer. Note we have to use {ARM|THUMB}_HARD_FRAME_POINTER_REGNUM
- because the definition of HARD_FRAME_POINTER_REGNUM is not a constant. */
-
-#define ELIMINABLE_REGS \
-{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM },\
- { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM },\
- { ARG_POINTER_REGNUM, ARM_HARD_FRAME_POINTER_REGNUM },\
- { ARG_POINTER_REGNUM, THUMB_HARD_FRAME_POINTER_REGNUM },\
- { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM },\
- { FRAME_POINTER_REGNUM, ARM_HARD_FRAME_POINTER_REGNUM },\
- { FRAME_POINTER_REGNUM, THUMB_HARD_FRAME_POINTER_REGNUM }}
-
-/* Given FROM and TO register numbers, say whether this elimination is
- allowed. Frame pointer elimination is automatically handled.
-
- All eliminations are permissible. Note that ARG_POINTER_REGNUM and
- HARD_FRAME_POINTER_REGNUM are in fact the same thing. If we need a frame
- pointer, we must eliminate FRAME_POINTER_REGNUM into
- HARD_FRAME_POINTER_REGNUM and not into STACK_POINTER_REGNUM or
- ARG_POINTER_REGNUM. */
-#define CAN_ELIMINATE(FROM, TO) \
- (((TO) == FRAME_POINTER_REGNUM && (FROM) == ARG_POINTER_REGNUM) ? 0 : \
- ((TO) == STACK_POINTER_REGNUM && frame_pointer_needed) ? 0 : \
- ((TO) == ARM_HARD_FRAME_POINTER_REGNUM && TARGET_THUMB) ? 0 : \
- ((TO) == THUMB_HARD_FRAME_POINTER_REGNUM && TARGET_ARM) ? 0 : \
- 1)
-
-/* Define the offset between two registers, one to be eliminated, and the
- other its replacement, at the start of a routine. */
-#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
- if (TARGET_ARM) \
- (OFFSET) = arm_compute_initial_elimination_offset (FROM, TO); \
- else \
- (OFFSET) = thumb_compute_initial_elimination_offset (FROM, TO)
-
-/* Special case handling of the location of arguments passed on the stack. */
-#define DEBUGGER_ARG_OFFSET(value, addr) value ? value : arm_debugger_arg_offset (value, addr)
-
-/* Initialize data used by insn expanders. This is called from insn_emit,
- once for every function before code is generated. */
-#define INIT_EXPANDERS arm_init_expanders ()
-
-/* Output assembler code for a block containing the constant parts
- of a trampoline, leaving space for the variable parts.
-
- 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
- XXX FIXME: When the trampoline returns, r8 will be clobbered. */
-#define ARM_TRAMPOLINE_TEMPLATE(FILE) \
-{ \
- asm_fprintf (FILE, "\tldr\t%r, [%r, #0]\n", \
- STATIC_CHAIN_REGNUM, PC_REGNUM); \
- asm_fprintf (FILE, "\tldr\t%r, [%r, #0]\n", \
- PC_REGNUM, PC_REGNUM); \
- assemble_aligned_integer (UNITS_PER_WORD, const0_rtx); \
- assemble_aligned_integer (UNITS_PER_WORD, const0_rtx); \
-}
-
-/* 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. */
-#define THUMB_TRAMPOLINE_TEMPLATE(FILE) \
-{ \
- fprintf (FILE, "\t.code 32\n"); \
- fprintf (FILE, ".Ltrampoline_start:\n"); \
- asm_fprintf (FILE, "\tldr\t%r, [%r, #8]\n", \
- STATIC_CHAIN_REGNUM, PC_REGNUM); \
- asm_fprintf (FILE, "\tldr\t%r, [%r, #8]\n", \
- IP_REGNUM, PC_REGNUM); \
- asm_fprintf (FILE, "\torr\t%r, %r, #1\n", \
- IP_REGNUM, IP_REGNUM); \
- asm_fprintf (FILE, "\tbx\t%r\n", IP_REGNUM); \
- fprintf (FILE, "\t.word\t0\n"); \
- fprintf (FILE, "\t.word\t0\n"); \
- fprintf (FILE, "\t.code 16\n"); \
-}
-
-#define TRAMPOLINE_TEMPLATE(FILE) \
- if (TARGET_ARM) \
- ARM_TRAMPOLINE_TEMPLATE (FILE) \
- else \
- THUMB_TRAMPOLINE_TEMPLATE (FILE)
-
-/* Length in units of the trampoline for entering a nested function. */
-#define TRAMPOLINE_SIZE (TARGET_ARM ? 16 : 24)
-
-/* Alignment required for a trampoline in bits. */
-#define TRAMPOLINE_ALIGNMENT 32
-
-
-/* Emit RTL insns to initialize the variable parts of a trampoline.
- FNADDR is an RTX for the address of the function's pure code.
- CXT is an RTX for the static chain value for the function. */
-#ifndef INITIALIZE_TRAMPOLINE
-#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
-{ \
- emit_move_insn (gen_rtx_MEM (SImode, \
- plus_constant (TRAMP, \
- TARGET_ARM ? 8 : 16)), \
- CXT); \
- emit_move_insn (gen_rtx_MEM (SImode, \
- plus_constant (TRAMP, \
- TARGET_ARM ? 12 : 20)), \
- FNADDR); \
- emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__clear_cache"), \
- 0, VOIDmode, 2, TRAMP, Pmode, \
- plus_constant (TRAMP, TRAMPOLINE_SIZE), Pmode); \
-}
-#endif
-
-
-/* Addressing modes, and classification of registers for them. */
-#define HAVE_POST_INCREMENT 1
-#define HAVE_PRE_INCREMENT TARGET_ARM
-#define HAVE_POST_DECREMENT TARGET_ARM
-#define HAVE_PRE_DECREMENT TARGET_ARM
-#define HAVE_PRE_MODIFY_DISP TARGET_ARM
-#define HAVE_POST_MODIFY_DISP TARGET_ARM
-#define HAVE_PRE_MODIFY_REG TARGET_ARM
-#define HAVE_POST_MODIFY_REG TARGET_ARM
-
-/* Macros to check register numbers against specific register classes. */
-
-/* These assume that REGNO is a hard or pseudo reg number.
- They give nonzero only if REGNO is a hard reg of the suitable class
- or a pseudo reg currently allocated to a suitable hard reg.
- Since they use reg_renumber, they are safe only once reg_renumber
- has been allocated, which happens in local-alloc.c. */
-#define TEST_REGNO(R, TEST, VALUE) \
- ((R TEST VALUE) || ((unsigned) reg_renumber[R] TEST VALUE))
-
-/* On the ARM, don't allow the pc to be used. */
-#define ARM_REGNO_OK_FOR_BASE_P(REGNO) \
- (TEST_REGNO (REGNO, <, PC_REGNUM) \
- || TEST_REGNO (REGNO, ==, FRAME_POINTER_REGNUM) \
- || TEST_REGNO (REGNO, ==, ARG_POINTER_REGNUM))
-
-#define THUMB_REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) \
- (TEST_REGNO (REGNO, <=, LAST_LO_REGNUM) \
- || (GET_MODE_SIZE (MODE) >= 4 \
- && TEST_REGNO (REGNO, ==, STACK_POINTER_REGNUM)))
-
-#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) \
- (TARGET_THUMB \
- ? THUMB_REGNO_MODE_OK_FOR_BASE_P (REGNO, MODE) \
- : ARM_REGNO_OK_FOR_BASE_P (REGNO))
-
-/* Nonzero if X can be the base register in a reg+reg addressing mode.
- For Thumb, we can not use SP + reg, so reject SP. */
-#define REGNO_MODE_OK_FOR_REG_BASE_P(X, MODE) \
- REGNO_OK_FOR_INDEX_P (X)
-
-/* For ARM code, we don't care about the mode, but for Thumb, the index
- must be suitable for use in a QImode load. */
-#define REGNO_OK_FOR_INDEX_P(REGNO) \
- REGNO_MODE_OK_FOR_BASE_P (REGNO, QImode)
-
-/* Maximum number of registers that can appear in a valid memory address.
- Shifts in addresses can't be by a register. */
-#define MAX_REGS_PER_ADDRESS 2
-
-/* Recognize any constant value that is a valid address. */
-/* XXX We can address any constant, eventually... */
-
-#ifdef AOF_ASSEMBLER
-
-#define CONSTANT_ADDRESS_P(X) \
- (GET_CODE (X) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (X))
-
-#else
-
-#define CONSTANT_ADDRESS_P(X) \
- (GET_CODE (X) == SYMBOL_REF \
- && (CONSTANT_POOL_ADDRESS_P (X) \
- || (TARGET_ARM && optimize > 0 && SYMBOL_REF_FLAG (X))))
-
-#endif /* AOF_ASSEMBLER */
-
-/* Nonzero if the constant value X is a legitimate general operand.
- It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.
-
- On the ARM, allow any integer (invalid ones are removed later by insn
- patterns), nice doubles and symbol_refs which refer to the function's
- constant pool XXX.
-
- When generating pic allow anything. */
-#define ARM_LEGITIMATE_CONSTANT_P(X) (flag_pic || ! label_mentioned_p (X))
-
-#define THUMB_LEGITIMATE_CONSTANT_P(X) \
- ( GET_CODE (X) == CONST_INT \
- || GET_CODE (X) == CONST_DOUBLE \
- || CONSTANT_ADDRESS_P (X) \
- || flag_pic)
-
-#define LEGITIMATE_CONSTANT_P(X) \
- (!arm_tls_referenced_p (X) \
- && (TARGET_ARM ? ARM_LEGITIMATE_CONSTANT_P (X) \
- : THUMB_LEGITIMATE_CONSTANT_P (X)))
-
-/* Special characters prefixed to function names
- in order to encode attribute like information.
- Note, '@' and '*' have already been taken. */
-#define SHORT_CALL_FLAG_CHAR '^'
-#define LONG_CALL_FLAG_CHAR '#'
-
-#define ENCODED_SHORT_CALL_ATTR_P(SYMBOL_NAME) \
- (*(SYMBOL_NAME) == SHORT_CALL_FLAG_CHAR)
-
-#define ENCODED_LONG_CALL_ATTR_P(SYMBOL_NAME) \
- (*(SYMBOL_NAME) == LONG_CALL_FLAG_CHAR)
-
-#ifndef SUBTARGET_NAME_ENCODING_LENGTHS
-#define SUBTARGET_NAME_ENCODING_LENGTHS
-#endif
-
-/* This is a C fragment for the inside of a switch statement.
- Each case label should return the number of characters to
- be stripped from the start of a function's name, if that
- name starts with the indicated character. */
-#define ARM_NAME_ENCODING_LENGTHS \
- case SHORT_CALL_FLAG_CHAR: return 1; \
- case LONG_CALL_FLAG_CHAR: return 1; \
- case '*': return 1; \
- SUBTARGET_NAME_ENCODING_LENGTHS
-
-/* This is how to output a reference to a user-level label named NAME.
- `assemble_name' uses this. */
-#undef ASM_OUTPUT_LABELREF
-#define ASM_OUTPUT_LABELREF(FILE, NAME) \
- arm_asm_output_labelref (FILE, NAME)
-
-/* The EABI specifies that constructors should go in .init_array.
- Other targets use .ctors for compatibility. */
-#ifndef ARM_EABI_CTORS_SECTION_OP
-#define ARM_EABI_CTORS_SECTION_OP \
- "\t.section\t.init_array,\"aw\",%init_array"
-#endif
-#ifndef ARM_EABI_DTORS_SECTION_OP
-#define ARM_EABI_DTORS_SECTION_OP \
- "\t.section\t.fini_array,\"aw\",%fini_array"
-#endif
-#define ARM_CTORS_SECTION_OP \
- "\t.section\t.ctors,\"aw\",%progbits"
-#define ARM_DTORS_SECTION_OP \
- "\t.section\t.dtors,\"aw\",%progbits"
-
-/* Define CTORS_SECTION_ASM_OP. */
-#undef CTORS_SECTION_ASM_OP
-#undef DTORS_SECTION_ASM_OP
-#ifndef IN_LIBGCC2
-# define CTORS_SECTION_ASM_OP \
- (TARGET_AAPCS_BASED ? ARM_EABI_CTORS_SECTION_OP : ARM_CTORS_SECTION_OP)
-# define DTORS_SECTION_ASM_OP \
- (TARGET_AAPCS_BASED ? ARM_EABI_DTORS_SECTION_OP : ARM_DTORS_SECTION_OP)
-#else /* !defined (IN_LIBGCC2) */
-/* In libgcc, CTORS_SECTION_ASM_OP must be a compile-time constant,
- so we cannot use the definition above. */
-# ifdef __ARM_EABI__
-/* The .ctors section is not part of the EABI, so we do not define
- CTORS_SECTION_ASM_OP when in libgcc; that prevents crtstuff
- from trying to use it. We do define it when doing normal
- compilation, as .init_array can be used instead of .ctors. */
-/* There is no need to emit begin or end markers when using
- init_array; the dynamic linker will compute the size of the
- array itself based on special symbols created by the static
- linker. However, we do need to arrange to set up
- exception-handling here. */
-# define CTOR_LIST_BEGIN asm (ARM_EABI_CTORS_SECTION_OP)
-# define CTOR_LIST_END /* empty */
-# define DTOR_LIST_BEGIN asm (ARM_EABI_DTORS_SECTION_OP)
-# define DTOR_LIST_END /* empty */
-# else /* !defined (__ARM_EABI__) */
-# define CTORS_SECTION_ASM_OP ARM_CTORS_SECTION_OP
-# define DTORS_SECTION_ASM_OP ARM_DTORS_SECTION_OP
-# endif /* !defined (__ARM_EABI__) */
-#endif /* !defined (IN_LIBCC2) */
-
-/* True if the operating system can merge entities with vague linkage
- (e.g., symbols in COMDAT group) during dynamic linking. */
-#ifndef TARGET_ARM_DYNAMIC_VAGUE_LINKAGE_P
-#define TARGET_ARM_DYNAMIC_VAGUE_LINKAGE_P true
-#endif
-
-/* Set the short-call flag for any function compiled in the current
- compilation unit. We skip this for functions with the section
- attribute when long-calls are in effect as this tells the compiler
- that the section might be placed a long way from the caller.
- See arm_is_longcall_p() for more information. */
-#define ARM_DECLARE_FUNCTION_SIZE(STREAM, NAME, DECL) \
- if (!TARGET_LONG_CALLS || ! DECL_SECTION_NAME (DECL)) \
- arm_encode_call_attribute (DECL, SHORT_CALL_FLAG_CHAR)
-
-#define ARM_OUTPUT_FN_UNWIND(F, PROLOGUE) arm_output_fn_unwind (F, PROLOGUE)
-
-#ifdef TARGET_UNWIND_INFO
-#define ARM_EABI_UNWIND_TABLES \
- ((!USING_SJLJ_EXCEPTIONS && flag_exceptions) || flag_unwind_tables)
-#else
-#define ARM_EABI_UNWIND_TABLES 0
-#endif
-
-/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
- and check its validity for a certain class.
- We have two alternate definitions for each of them.
- The usual definition accepts all pseudo regs; the other rejects
- them unless they have been allocated suitable hard regs.
- The symbol REG_OK_STRICT causes the latter definition to be used. */
-#ifndef REG_OK_STRICT
-
-#define ARM_REG_OK_FOR_BASE_P(X) \
- (REGNO (X) <= LAST_ARM_REGNUM \
- || REGNO (X) >= FIRST_PSEUDO_REGISTER \
- || REGNO (X) == FRAME_POINTER_REGNUM \
- || REGNO (X) == ARG_POINTER_REGNUM)
-
-#define THUMB_REG_MODE_OK_FOR_BASE_P(X, MODE) \
- (REGNO (X) <= LAST_LO_REGNUM \
- || REGNO (X) >= FIRST_PSEUDO_REGISTER \
- || (GET_MODE_SIZE (MODE) >= 4 \
- && (REGNO (X) == STACK_POINTER_REGNUM \
- || (X) == hard_frame_pointer_rtx \
- || (X) == arg_pointer_rtx)))
-
-#define REG_STRICT_P 0
-
-#else /* REG_OK_STRICT */
-
-#define ARM_REG_OK_FOR_BASE_P(X) \
- ARM_REGNO_OK_FOR_BASE_P (REGNO (X))
-
-#define THUMB_REG_MODE_OK_FOR_BASE_P(X, MODE) \
- THUMB_REGNO_MODE_OK_FOR_BASE_P (REGNO (X), MODE)
-
-#define REG_STRICT_P 1
-
-#endif /* REG_OK_STRICT */
-
-/* Now define some helpers in terms of the above. */
-
-#define REG_MODE_OK_FOR_BASE_P(X, MODE) \
- (TARGET_THUMB \
- ? THUMB_REG_MODE_OK_FOR_BASE_P (X, MODE) \
- : ARM_REG_OK_FOR_BASE_P (X))
-
-#define ARM_REG_OK_FOR_INDEX_P(X) ARM_REG_OK_FOR_BASE_P (X)
-
-/* For Thumb, a valid index register is anything that can be used in
- a byte load instruction. */
-#define THUMB_REG_OK_FOR_INDEX_P(X) THUMB_REG_MODE_OK_FOR_BASE_P (X, QImode)
-
-/* Nonzero if X is a hard reg that can be used as an index
- or if it is a pseudo reg. On the Thumb, the stack pointer
- is not suitable. */
-#define REG_OK_FOR_INDEX_P(X) \
- (TARGET_THUMB \
- ? THUMB_REG_OK_FOR_INDEX_P (X) \
- : ARM_REG_OK_FOR_INDEX_P (X))
-
-/* Nonzero if X can be the base register in a reg+reg addressing mode.
- For Thumb, we can not use SP + reg, so reject SP. */
-#define REG_MODE_OK_FOR_REG_BASE_P(X, MODE) \
- REG_OK_FOR_INDEX_P (X)
-
-/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
- that is a valid memory address for an instruction.
- The MODE argument is the machine mode for the MEM expression
- that wants to use this address. */
-
-#define ARM_BASE_REGISTER_RTX_P(X) \
- (GET_CODE (X) == REG && ARM_REG_OK_FOR_BASE_P (X))
-
-#define ARM_INDEX_REGISTER_RTX_P(X) \
- (GET_CODE (X) == REG && ARM_REG_OK_FOR_INDEX_P (X))
-
-#define ARM_GO_IF_LEGITIMATE_ADDRESS(MODE,X,WIN) \
- { \
- if (arm_legitimate_address_p (MODE, X, SET, REG_STRICT_P)) \
- goto WIN; \
- }
-
-#define THUMB_GO_IF_LEGITIMATE_ADDRESS(MODE,X,WIN) \
- { \
- if (thumb_legitimate_address_p (MODE, X, REG_STRICT_P)) \
- goto WIN; \
- }
-
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, WIN) \
- if (TARGET_ARM) \
- ARM_GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN) \
- else /* if (TARGET_THUMB) */ \
- THUMB_GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN)
-
-
-/* Try machine-dependent ways of modifying an illegitimate address
- to be legitimate. If we find one, return the new, valid address. */
-#define ARM_LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
-do { \
- X = arm_legitimize_address (X, OLDX, MODE); \
-} while (0)
-
-#define THUMB_LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
-do { \
- X = thumb_legitimize_address (X, OLDX, MODE); \
-} while (0)
-
-#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
-do { \
- if (TARGET_ARM) \
- ARM_LEGITIMIZE_ADDRESS (X, OLDX, MODE, WIN); \
- else \
- THUMB_LEGITIMIZE_ADDRESS (X, OLDX, MODE, WIN); \
- \
- if (memory_address_p (MODE, X)) \
- goto WIN; \
-} while (0)
-
-/* Go to LABEL if ADDR (a legitimate address expression)
- has an effect that depends on the machine mode it is used for. */
-#define ARM_GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \
-{ \
- if ( GET_CODE (ADDR) == PRE_DEC || GET_CODE (ADDR) == POST_DEC \
- || GET_CODE (ADDR) == PRE_INC || GET_CODE (ADDR) == POST_INC) \
- goto LABEL; \
-}
-
-/* Nothing helpful to do for the Thumb */
-#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \
- if (TARGET_ARM) \
- ARM_GO_IF_MODE_DEPENDENT_ADDRESS (ADDR, LABEL)
-
-
-/* Specify the machine mode that this machine uses
- for the index in the tablejump instruction. */
-#define CASE_VECTOR_MODE Pmode
-
-/* signed 'char' is most compatible, but RISC OS wants it unsigned.
- unsigned is probably best, but may break some code. */
-#ifndef DEFAULT_SIGNED_CHAR
-#define DEFAULT_SIGNED_CHAR 0
-#endif
-
-/* Max number of bytes we can move from memory to memory
- in one reasonably fast instruction. */
-#define MOVE_MAX 4
-
-#undef MOVE_RATIO
-#define MOVE_RATIO (arm_tune_xscale ? 4 : 2)
-
-/* Define if operations between registers always perform the operation
- on the full register even if a narrower mode is specified. */
-#define WORD_REGISTER_OPERATIONS
-
-/* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD
- will either zero-extend or sign-extend. The value of this macro should
- be the code that says which one of the two operations is implicitly
- done, UNKNOWN if none. */
-#define LOAD_EXTEND_OP(MODE) \
- (TARGET_THUMB ? ZERO_EXTEND : \
- ((arm_arch4 || (MODE) == QImode) ? ZERO_EXTEND \
- : ((BYTES_BIG_ENDIAN && (MODE) == HImode) ? SIGN_EXTEND : UNKNOWN)))
-
-/* Nonzero if access to memory by bytes is slow and undesirable. */
-#define SLOW_BYTE_ACCESS 0
-
-#define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) 1
-
-/* Immediate shift counts are truncated by the output routines (or was it
- the assembler?). Shift counts in a register are truncated by ARM. Note
- that the native compiler puts too large (> 32) immediate shift counts
- into a register and shifts by the register, letting the ARM decide what
- to do instead of doing that itself. */
-/* This is all wrong. Defining SHIFT_COUNT_TRUNCATED tells combine that
- code like (X << (Y % 32)) for register X, Y is equivalent to (X << Y).
- On the arm, Y in a register is used modulo 256 for the shift. Only for
- rotates is modulo 32 used. */
-/* #define SHIFT_COUNT_TRUNCATED 1 */
-
-/* All integers have the same format so truncation is easy. */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
-/* Calling from registers is a massive pain. */
-#define NO_FUNCTION_CSE 1
-
-/* The machine modes of pointers and functions */
-#define Pmode SImode
-#define FUNCTION_MODE Pmode
-
-#define ARM_FRAME_RTX(X) \
- ( (X) == frame_pointer_rtx || (X) == stack_pointer_rtx \
- || (X) == arg_pointer_rtx)
-
-/* Moves to and from memory are quite expensive */
-#define MEMORY_MOVE_COST(M, CLASS, IN) \
- (TARGET_ARM ? 10 : \
- ((GET_MODE_SIZE (M) < 4 ? 8 : 2 * GET_MODE_SIZE (M)) \
- * (CLASS == LO_REGS ? 1 : 2)))
-
-/* Try to generate sequences that don't involve branches, we can then use
- conditional instructions */
-#define BRANCH_COST \
- (TARGET_ARM ? 4 : (optimize > 1 ? 1 : 0))
-
-/* Position Independent Code. */
-/* We decide which register to use based on the compilation options and
- the assembler in use; this is more general than the APCS restriction of
- using sb (r9) all the time. */
-extern unsigned arm_pic_register;
-
-/* The register number of the register used to address a table of static
- data addresses in memory. */
-#define PIC_OFFSET_TABLE_REGNUM arm_pic_register
-
-/* We can't directly access anything that contains a symbol,
- nor can we indirect via the constant pool. One exception is
- UNSPEC_TLS, which is always PIC. */
-#define LEGITIMATE_PIC_OPERAND_P(X) \
- (!(symbol_mentioned_p (X) \
- || label_mentioned_p (X) \
- || (GET_CODE (X) == SYMBOL_REF \
- && CONSTANT_POOL_ADDRESS_P (X) \
- && (symbol_mentioned_p (get_pool_constant (X)) \
- || label_mentioned_p (get_pool_constant (X))))) \
- || tls_mentioned_p (X))
-
-/* We need to know when we are making a constant pool; this determines
- whether data needs to be in the GOT or can be referenced via a GOT
- offset. */
-extern int making_const_table;
-
-/* Handle pragmas for compatibility with Intel's compilers. */
-#define REGISTER_TARGET_PRAGMAS() do { \
- c_register_pragma (0, "long_calls", arm_pr_long_calls); \
- c_register_pragma (0, "no_long_calls", arm_pr_no_long_calls); \
- c_register_pragma (0, "long_calls_off", arm_pr_long_calls_off); \
-} while (0)
-
-/* Condition code information. */
-/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
- return the mode to be used for the comparison. */
-
-#define SELECT_CC_MODE(OP, X, Y) arm_select_cc_mode (OP, X, Y)
-
-#define REVERSIBLE_CC_MODE(MODE) 1
-
-#define REVERSE_CONDITION(CODE,MODE) \
- (((MODE) == CCFPmode || (MODE) == CCFPEmode) \
- ? reverse_condition_maybe_unordered (code) \
- : reverse_condition (code))
-
-#define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
- do \
- { \
- if (GET_CODE (OP1) == CONST_INT \
- && ! (const_ok_for_arm (INTVAL (OP1)) \
- || (const_ok_for_arm (- INTVAL (OP1))))) \
- { \
- rtx const_op = OP1; \
- CODE = arm_canonicalize_comparison ((CODE), GET_MODE (OP0), \
- &const_op); \
- OP1 = const_op; \
- } \
- } \
- while (0)
-
-/* The arm5 clz instruction returns 32. */
-#define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1)
-
-#undef ASM_APP_OFF
-#define ASM_APP_OFF (TARGET_THUMB ? "\t.code\t16\n" : "")
-
-/* Output a push or a pop instruction (only used when profiling). */
-#define ASM_OUTPUT_REG_PUSH(STREAM, REGNO) \
- do \
- { \
- if (TARGET_ARM) \
- asm_fprintf (STREAM,"\tstmfd\t%r!,{%r}\n", \
- STACK_POINTER_REGNUM, REGNO); \
- else \
- asm_fprintf (STREAM, "\tpush {%r}\n", REGNO); \
- } while (0)
-
-
-#define ASM_OUTPUT_REG_POP(STREAM, REGNO) \
- do \
- { \
- if (TARGET_ARM) \
- asm_fprintf (STREAM, "\tldmfd\t%r!,{%r}\n", \
- STACK_POINTER_REGNUM, REGNO); \
- else \
- asm_fprintf (STREAM, "\tpop {%r}\n", REGNO); \
- } while (0)
-
-/* This is how to output a label which precedes a jumptable. Since
- Thumb instructions are 2 bytes, we may need explicit alignment here. */
-#undef ASM_OUTPUT_CASE_LABEL
-#define ASM_OUTPUT_CASE_LABEL(FILE, PREFIX, NUM, JUMPTABLE) \
- do \
- { \
- if (TARGET_THUMB) \
- ASM_OUTPUT_ALIGN (FILE, 2); \
- (*targetm.asm_out.internal_label) (FILE, PREFIX, NUM); \
- } \
- while (0)
-
-#define ARM_DECLARE_FUNCTION_NAME(STREAM, NAME, DECL) \
- do \
- { \
- if (TARGET_THUMB) \
- { \
- if (is_called_in_ARM_mode (DECL) \
- || current_function_is_thunk) \
- fprintf (STREAM, "\t.code 32\n") ; \
- else \
- fprintf (STREAM, "\t.code 16\n\t.thumb_func\n") ; \
- } \
- if (TARGET_POKE_FUNCTION_NAME) \
- arm_poke_function_name (STREAM, (char *) NAME); \
- } \
- while (0)
-
-/* For aliases of functions we use .thumb_set instead. */
-#define ASM_OUTPUT_DEF_FROM_DECLS(FILE, DECL1, DECL2) \
- do \
- { \
- const char *const LABEL1 = XSTR (XEXP (DECL_RTL (decl), 0), 0); \
- const char *const LABEL2 = IDENTIFIER_POINTER (DECL2); \
- \
- if (TARGET_THUMB && 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)
-
-#ifdef HAVE_GAS_MAX_SKIP_P2ALIGN
-/* To support -falign-* switches we need to use .p2align so
- that alignment directives in code sections will be padded
- with no-op instructions, rather than zeroes. */
-#define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE, LOG, MAX_SKIP) \
- if ((LOG) != 0) \
- { \
- if ((MAX_SKIP) == 0) \
- fprintf ((FILE), "\t.p2align %d\n", (int) (LOG)); \
- else \
- fprintf ((FILE), "\t.p2align %d,,%d\n", \
- (int) (LOG), (int) (MAX_SKIP)); \
- }
-#endif
-
-/* Only perform branch elimination (by making instructions conditional) if
- we're optimizing. Otherwise it's of no use anyway. */
-#define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \
- if (TARGET_ARM && optimize) \
- arm_final_prescan_insn (INSN); \
- else if (TARGET_THUMB) \
- thumb_final_prescan_insn (INSN)
-
-#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
- (CODE == '@' || CODE == '|' \
- || (TARGET_ARM && (CODE == '?')) \
- || (TARGET_THUMB && (CODE == '_')))
-
-/* Output an operand of an instruction. */
-#define PRINT_OPERAND(STREAM, X, CODE) \
- arm_print_operand (STREAM, X, CODE)
-
-#define ARM_SIGN_EXTEND(x) ((HOST_WIDE_INT) \
- (HOST_BITS_PER_WIDE_INT <= 32 ? (unsigned HOST_WIDE_INT) (x) \
- : ((((unsigned HOST_WIDE_INT)(x)) & (unsigned HOST_WIDE_INT) 0xffffffff) |\
- ((((unsigned HOST_WIDE_INT)(x)) & (unsigned HOST_WIDE_INT) 0x80000000) \
- ? ((~ (unsigned HOST_WIDE_INT) 0) \
- & ~ (unsigned HOST_WIDE_INT) 0xffffffff) \
- : 0))))
-
-/* Output the address of an operand. */
-#define ARM_PRINT_OPERAND_ADDRESS(STREAM, X) \
-{ \
- int is_minus = GET_CODE (X) == MINUS; \
- \
- if (GET_CODE (X) == REG) \
- asm_fprintf (STREAM, "[%r, #0]", REGNO (X)); \
- else if (GET_CODE (X) == PLUS || is_minus) \
- { \
- rtx base = XEXP (X, 0); \
- rtx index = XEXP (X, 1); \
- HOST_WIDE_INT offset = 0; \
- if (GET_CODE (base) != REG) \
- { \
- /* Ensure that BASE is a register. */ \
- /* (one of them must be). */ \
- rtx temp = base; \
- base = index; \
- index = temp; \
- } \
- switch (GET_CODE (index)) \
- { \
- case CONST_INT: \
- offset = INTVAL (index); \
- if (is_minus) \
- offset = -offset; \
- asm_fprintf (STREAM, "[%r, #%wd]", \
- REGNO (base), offset); \
- break; \
- \
- case REG: \
- asm_fprintf (STREAM, "[%r, %s%r]", \
- REGNO (base), is_minus ? "-" : "", \
- REGNO (index)); \
- break; \
- \
- case MULT: \
- case ASHIFTRT: \
- case LSHIFTRT: \
- case ASHIFT: \
- case ROTATERT: \
- { \
- asm_fprintf (STREAM, "[%r, %s%r", \
- REGNO (base), is_minus ? "-" : "", \
- REGNO (XEXP (index, 0))); \
- arm_print_operand (STREAM, index, 'S'); \
- fputs ("]", STREAM); \
- break; \
- } \
- \
- default: \
- gcc_unreachable (); \
- } \
- } \
- else if (GET_CODE (X) == PRE_INC || GET_CODE (X) == POST_INC \
- || GET_CODE (X) == PRE_DEC || GET_CODE (X) == POST_DEC) \
- { \
- extern enum machine_mode output_memory_reference_mode; \
- \
- gcc_assert (GET_CODE (XEXP (X, 0)) == REG); \
- \
- if (GET_CODE (X) == PRE_DEC || GET_CODE (X) == PRE_INC) \
- asm_fprintf (STREAM, "[%r, #%s%d]!", \
- REGNO (XEXP (X, 0)), \
- GET_CODE (X) == PRE_DEC ? "-" : "", \
- GET_MODE_SIZE (output_memory_reference_mode)); \
- else \
- asm_fprintf (STREAM, "[%r], #%s%d", \
- REGNO (XEXP (X, 0)), \
- GET_CODE (X) == POST_DEC ? "-" : "", \
- GET_MODE_SIZE (output_memory_reference_mode)); \
- } \
- else if (GET_CODE (X) == PRE_MODIFY) \
- { \
- asm_fprintf (STREAM, "[%r, ", REGNO (XEXP (X, 0))); \
- if (GET_CODE (XEXP (XEXP (X, 1), 1)) == CONST_INT) \
- asm_fprintf (STREAM, "#%wd]!", \
- INTVAL (XEXP (XEXP (X, 1), 1))); \
- else \
- asm_fprintf (STREAM, "%r]!", \
- REGNO (XEXP (XEXP (X, 1), 1))); \
- } \
- else if (GET_CODE (X) == POST_MODIFY) \
- { \
- asm_fprintf (STREAM, "[%r], ", REGNO (XEXP (X, 0))); \
- if (GET_CODE (XEXP (XEXP (X, 1), 1)) == CONST_INT) \
- asm_fprintf (STREAM, "#%wd", \
- INTVAL (XEXP (XEXP (X, 1), 1))); \
- else \
- asm_fprintf (STREAM, "%r", \
- REGNO (XEXP (XEXP (X, 1), 1))); \
- } \
- else output_addr_const (STREAM, X); \
-}
-
-#define THUMB_PRINT_OPERAND_ADDRESS(STREAM, X) \
-{ \
- if (GET_CODE (X) == REG) \
- asm_fprintf (STREAM, "[%r]", REGNO (X)); \
- else if (GET_CODE (X) == POST_INC) \
- asm_fprintf (STREAM, "%r!", REGNO (XEXP (X, 0))); \
- else if (GET_CODE (X) == PLUS) \
- { \
- gcc_assert (GET_CODE (XEXP (X, 0)) == REG); \
- if (GET_CODE (XEXP (X, 1)) == CONST_INT) \
- asm_fprintf (STREAM, "[%r, #%wd]", \
- REGNO (XEXP (X, 0)), \
- INTVAL (XEXP (X, 1))); \
- else \
- asm_fprintf (STREAM, "[%r, %r]", \
- REGNO (XEXP (X, 0)), \
- REGNO (XEXP (X, 1))); \
- } \
- else \
- output_addr_const (STREAM, X); \
-}
-
-#define PRINT_OPERAND_ADDRESS(STREAM, X) \
- if (TARGET_ARM) \
- ARM_PRINT_OPERAND_ADDRESS (STREAM, X) \
- else \
- THUMB_PRINT_OPERAND_ADDRESS (STREAM, X)
-
-#define OUTPUT_ADDR_CONST_EXTRA(file, x, fail) \
- if (arm_output_addr_const_extra (file, x) == FALSE) \
- goto fail
-
-/* A C expression whose value is RTL representing the value of the return
- address for the frame COUNT steps up from the current frame. */
-
-#define RETURN_ADDR_RTX(COUNT, FRAME) \
- arm_return_addr (COUNT, FRAME)
-
-/* Mask of the bits in the PC that contain the real return address
- when running in 26-bit mode. */
-#define RETURN_ADDR_MASK26 (0x03fffffc)
-
-/* Pick up the return address upon entry to a procedure. Used for
- dwarf2 unwind information. This also enables the table driven
- mechanism. */
-#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, LR_REGNUM)
-#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (LR_REGNUM)
-
-/* Used to mask out junk bits from the return address, such as
- processor state, interrupt status, condition codes and the like. */
-#define MASK_RETURN_ADDR \
- /* If we are generating code for an ARM2/ARM3 machine or for an ARM6 \
- in 26 bit mode, the condition codes must be masked out of the \
- return address. This does not apply to ARM6 and later processors \
- when running in 32 bit mode. */ \
- ((arm_arch4 || TARGET_THUMB) \
- ? (gen_int_mode ((unsigned long)0xffffffff, Pmode)) \
- : arm_gen_return_addr_mask ())
-
-
-enum arm_builtins
-{
- ARM_BUILTIN_GETWCX,
- ARM_BUILTIN_SETWCX,
-
- ARM_BUILTIN_WZERO,
-
- ARM_BUILTIN_WAVG2BR,
- ARM_BUILTIN_WAVG2HR,
- ARM_BUILTIN_WAVG2B,
- ARM_BUILTIN_WAVG2H,
-
- ARM_BUILTIN_WACCB,
- ARM_BUILTIN_WACCH,
- ARM_BUILTIN_WACCW,
-
- ARM_BUILTIN_WMACS,
- ARM_BUILTIN_WMACSZ,
- ARM_BUILTIN_WMACU,
- ARM_BUILTIN_WMACUZ,
-
- ARM_BUILTIN_WSADB,
- ARM_BUILTIN_WSADBZ,
- ARM_BUILTIN_WSADH,
- ARM_BUILTIN_WSADHZ,
-
- ARM_BUILTIN_WALIGN,
-
- ARM_BUILTIN_TMIA,
- ARM_BUILTIN_TMIAPH,
- ARM_BUILTIN_TMIABB,
- ARM_BUILTIN_TMIABT,
- ARM_BUILTIN_TMIATB,
- ARM_BUILTIN_TMIATT,
-
- ARM_BUILTIN_TMOVMSKB,
- ARM_BUILTIN_TMOVMSKH,
- ARM_BUILTIN_TMOVMSKW,
-
- ARM_BUILTIN_TBCSTB,
- ARM_BUILTIN_TBCSTH,
- ARM_BUILTIN_TBCSTW,
-
- ARM_BUILTIN_WMADDS,
- ARM_BUILTIN_WMADDU,
-
- ARM_BUILTIN_WPACKHSS,
- ARM_BUILTIN_WPACKWSS,
- ARM_BUILTIN_WPACKDSS,
- ARM_BUILTIN_WPACKHUS,
- ARM_BUILTIN_WPACKWUS,
- ARM_BUILTIN_WPACKDUS,
-
- ARM_BUILTIN_WADDB,
- ARM_BUILTIN_WADDH,
- ARM_BUILTIN_WADDW,
- ARM_BUILTIN_WADDSSB,
- ARM_BUILTIN_WADDSSH,
- ARM_BUILTIN_WADDSSW,
- ARM_BUILTIN_WADDUSB,
- ARM_BUILTIN_WADDUSH,
- ARM_BUILTIN_WADDUSW,
- ARM_BUILTIN_WSUBB,
- ARM_BUILTIN_WSUBH,
- ARM_BUILTIN_WSUBW,
- ARM_BUILTIN_WSUBSSB,
- ARM_BUILTIN_WSUBSSH,
- ARM_BUILTIN_WSUBSSW,
- ARM_BUILTIN_WSUBUSB,
- ARM_BUILTIN_WSUBUSH,
- ARM_BUILTIN_WSUBUSW,
-
- ARM_BUILTIN_WAND,
- ARM_BUILTIN_WANDN,
- ARM_BUILTIN_WOR,
- ARM_BUILTIN_WXOR,
-
- ARM_BUILTIN_WCMPEQB,
- ARM_BUILTIN_WCMPEQH,
- ARM_BUILTIN_WCMPEQW,
- ARM_BUILTIN_WCMPGTUB,
- ARM_BUILTIN_WCMPGTUH,
- ARM_BUILTIN_WCMPGTUW,
- ARM_BUILTIN_WCMPGTSB,
- ARM_BUILTIN_WCMPGTSH,
- ARM_BUILTIN_WCMPGTSW,
-
- ARM_BUILTIN_TEXTRMSB,
- ARM_BUILTIN_TEXTRMSH,
- ARM_BUILTIN_TEXTRMSW,
- ARM_BUILTIN_TEXTRMUB,
- ARM_BUILTIN_TEXTRMUH,
- ARM_BUILTIN_TEXTRMUW,
- ARM_BUILTIN_TINSRB,
- ARM_BUILTIN_TINSRH,
- ARM_BUILTIN_TINSRW,
-
- ARM_BUILTIN_WMAXSW,
- ARM_BUILTIN_WMAXSH,
- ARM_BUILTIN_WMAXSB,
- ARM_BUILTIN_WMAXUW,
- ARM_BUILTIN_WMAXUH,
- ARM_BUILTIN_WMAXUB,
- ARM_BUILTIN_WMINSW,
- ARM_BUILTIN_WMINSH,
- ARM_BUILTIN_WMINSB,
- ARM_BUILTIN_WMINUW,
- ARM_BUILTIN_WMINUH,
- ARM_BUILTIN_WMINUB,
-
- ARM_BUILTIN_WMULUM,
- ARM_BUILTIN_WMULSM,
- ARM_BUILTIN_WMULUL,
-
- ARM_BUILTIN_PSADBH,
- ARM_BUILTIN_WSHUFH,
-
- ARM_BUILTIN_WSLLH,
- ARM_BUILTIN_WSLLW,
- ARM_BUILTIN_WSLLD,
- ARM_BUILTIN_WSRAH,
- ARM_BUILTIN_WSRAW,
- ARM_BUILTIN_WSRAD,
- ARM_BUILTIN_WSRLH,
- ARM_BUILTIN_WSRLW,
- ARM_BUILTIN_WSRLD,
- ARM_BUILTIN_WRORH,
- ARM_BUILTIN_WRORW,
- ARM_BUILTIN_WRORD,
- ARM_BUILTIN_WSLLHI,
- ARM_BUILTIN_WSLLWI,
- ARM_BUILTIN_WSLLDI,
- ARM_BUILTIN_WSRAHI,
- ARM_BUILTIN_WSRAWI,
- ARM_BUILTIN_WSRADI,
- ARM_BUILTIN_WSRLHI,
- ARM_BUILTIN_WSRLWI,
- ARM_BUILTIN_WSRLDI,
- ARM_BUILTIN_WRORHI,
- ARM_BUILTIN_WRORWI,
- ARM_BUILTIN_WRORDI,
-
- ARM_BUILTIN_WUNPCKIHB,
- ARM_BUILTIN_WUNPCKIHH,
- ARM_BUILTIN_WUNPCKIHW,
- ARM_BUILTIN_WUNPCKILB,
- ARM_BUILTIN_WUNPCKILH,
- ARM_BUILTIN_WUNPCKILW,
-
- ARM_BUILTIN_WUNPCKEHSB,
- ARM_BUILTIN_WUNPCKEHSH,
- ARM_BUILTIN_WUNPCKEHSW,
- ARM_BUILTIN_WUNPCKEHUB,
- ARM_BUILTIN_WUNPCKEHUH,
- ARM_BUILTIN_WUNPCKEHUW,
- ARM_BUILTIN_WUNPCKELSB,
- ARM_BUILTIN_WUNPCKELSH,
- ARM_BUILTIN_WUNPCKELSW,
- ARM_BUILTIN_WUNPCKELUB,
- ARM_BUILTIN_WUNPCKELUH,
- ARM_BUILTIN_WUNPCKELUW,
-
- ARM_BUILTIN_THREAD_POINTER,
-
- ARM_BUILTIN_MAX
-};
-
-/* Do not emit .note.GNU-stack by default. */
-#ifndef NEED_INDICATE_EXEC_STACK
-#define NEED_INDICATE_EXEC_STACK 0
-#endif
-
-#endif /* ! GCC_ARM_H */
diff --git a/gcc-4.2.1/gcc/config/arm/arm.md b/gcc-4.2.1/gcc/config/arm/arm.md
deleted file mode 100644
index b28e3d01a..000000000
--- a/gcc-4.2.1/gcc/config/arm/arm.md
+++ /dev/null
@@ -1,10304 +0,0 @@
-;;- Machine description for ARM for GNU compiler
-;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
-;; 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
-;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
-;; and Martin Simmons (@harleqn.co.uk).
-;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
-
-;; This file is part of GCC.
-
-;; GCC is free software; you can redistribute it and/or modify it
-;; under the terms of the GNU General Public License as published
-;; by the Free Software Foundation; either version 2, or (at your
-;; option) any later version.
-
-;; GCC is distributed in the hope that it will be useful, but WITHOUT
-;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
-;; License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
-
-;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
-
-
-;;---------------------------------------------------------------------------
-;; Constants
-
-;; Register numbers
-(define_constants
- [(R0_REGNUM 0) ; First CORE register
- (IP_REGNUM 12) ; Scratch register
- (SP_REGNUM 13) ; Stack pointer
- (LR_REGNUM 14) ; Return address register
- (PC_REGNUM 15) ; Program counter
- (CC_REGNUM 24) ; Condition code pseudo register
- (LAST_ARM_REGNUM 15) ;
- (FPA_F0_REGNUM 16) ; FIRST_FPA_REGNUM
- (FPA_F7_REGNUM 23) ; LAST_FPA_REGNUM
- ]
-)
-;; 3rd operand to select_dominance_cc_mode
-(define_constants
- [(DOM_CC_X_AND_Y 0)
- (DOM_CC_NX_OR_Y 1)
- (DOM_CC_X_OR_Y 2)
- ]
-)
-
-;; UNSPEC Usage:
-;; Note: sin and cos are no-longer used.
-
-(define_constants
- [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
- ; operand 0 is the result,
- ; operand 1 the parameter.
- (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
- ; operand 0 is the result,
- ; operand 1 the parameter.
- (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
- ; operand 0 is the first register,
- ; subsequent registers are in parallel (use ...)
- ; expressions.
- (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
- ; usage, that is, we will add the pic_register
- ; value to it before trying to dereference it.
- (UNSPEC_PIC_BASE 4) ; Adding the PC value to the offset to the
- ; GLOBAL_OFFSET_TABLE. The operation is fully
- ; described by the RTL but must be wrapped to
- ; prevent combine from trying to rip it apart.
- (UNSPEC_PRLG_STK 5) ; A special barrier that prevents frame accesses
- ; being scheduled before the stack adjustment insn.
- (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
- ; this unspec is used to prevent the deletion of
- ; instructions setting registers for EH handling
- ; and stack frame generation. Operand 0 is the
- ; register to "use".
- (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
- (UNSPEC_WSHUFH 8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
- (UNSPEC_WACC 9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
- (UNSPEC_TMOVMSK 10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
- (UNSPEC_WSAD 11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
- (UNSPEC_WSADZ 12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
- (UNSPEC_WMACS 13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
- (UNSPEC_WMACU 14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
- (UNSPEC_WMACSZ 15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
- (UNSPEC_WMACUZ 16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
- (UNSPEC_CLRDI 17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
- (UNSPEC_WMADDS 18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
- (UNSPEC_WMADDU 19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
- (UNSPEC_TLS 20) ; A symbol that has been treated properly for TLS usage.
- (UNSPEC_PIC_LABEL 21) ; A label used for PIC access that does not appear in the
- ; instruction stream.
- ]
-)
-
-;; UNSPEC_VOLATILE Usage:
-
-(define_constants
- [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
- ; insn in the code.
- (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
- ; instruction epilogue sequence that isn't expanded
- ; into normal RTL. Used for both normal and sibcall
- ; epilogues.
- (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
- ; for inlined constants.
- (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
- ; table.
- (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
- ; an 8-bit object.
- (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
- ; a 16-bit object.
- (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
- ; a 32-bit object.
- (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
- ; a 64-bit object.
- (VUNSPEC_TMRC 8) ; Used by the iWMMXt TMRC instruction.
- (VUNSPEC_TMCR 9) ; Used by the iWMMXt TMCR instruction.
- (VUNSPEC_ALIGN8 10) ; 8-byte alignment version of VUNSPEC_ALIGN
- (VUNSPEC_WCMP_EQ 11) ; Used by the iWMMXt WCMPEQ instructions
- (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
- (VUNSPEC_WCMP_GT 13) ; Used by the iwMMXT WCMPGT instructions
- (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
- ; handling.
- ]
-)
-
-;;---------------------------------------------------------------------------
-;; Attributes
-
-; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
-; generating ARM code. This is used to control the length of some insn
-; patterns that share the same RTL in both ARM and Thumb code.
-(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
-
-; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
-; scheduling decisions for the load unit and the multiplier.
-(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))
-
-; IS_XSCALE is set to 'yes' when compiling for XScale.
-(define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
-
-;; Operand number of an input operand that is shifted. Zero if the
-;; given instruction does not shift one of its input operands.
-(define_attr "shift" "" (const_int 0))
-
-; Floating Point Unit. If we only have floating point emulation, then there
-; is no point in scheduling the floating point insns. (Well, for best
-; performance we should try and group them together).
-(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
- (const (symbol_ref "arm_fpu_attr")))
-
-; LENGTH of an instruction (in bytes)
-(define_attr "length" "" (const_int 4))
-
-; POOL_RANGE is how far away from a constant pool entry that this insn
-; can be placed. If the distance is zero, then this insn will never
-; reference the pool.
-; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
-; before its address.
-(define_attr "pool_range" "" (const_int 0))
-(define_attr "neg_pool_range" "" (const_int 0))
-
-; An assembler sequence may clobber the condition codes without us knowing.
-; If such an insn references the pool, then we have no way of knowing how,
-; so use the most conservative value for pool_range.
-(define_asm_attributes
- [(set_attr "conds" "clob")
- (set_attr "length" "4")
- (set_attr "pool_range" "250")])
-
-;; The instruction used to implement a particular pattern. This
-;; information is used by pipeline descriptions to provide accurate
-;; scheduling information.
-
-(define_attr "insn"
- "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,other"
- (const_string "other"))
-
-; TYPE attribute is used to detect floating point instructions which, if
-; running on a co-processor can run in parallel with other, basic instructions
-; If write-buffer scheduling is enabled then it can also be used in the
-; scheduling of writes.
-
-; Classification of each insn
-; alu any alu instruction that doesn't hit memory or fp
-; regs or have a shifted source operand
-; alu_shift any data instruction that doesn't hit memory or fp
-; regs, but has a source operand shifted by a constant
-; alu_shift_reg any data instruction that doesn't hit memory or fp
-; regs, but has a source operand shifted by a register value
-; mult a multiply instruction
-; block blockage insn, this blocks all functional units
-; float a floating point arithmetic operation (subject to expansion)
-; fdivd DFmode floating point division
-; fdivs SFmode floating point division
-; fmul Floating point multiply
-; ffmul Fast floating point multiply
-; farith Floating point arithmetic (4 cycle)
-; ffarith Fast floating point arithmetic (2 cycle)
-; float_em a floating point arithmetic operation that is normally emulated
-; even on a machine with an fpa.
-; f_load a floating point load from memory
-; f_store a floating point store to memory
-; f_load[sd] single/double load from memory
-; f_store[sd] single/double store to memory
-; f_flag a transfer of co-processor flags to the CPSR
-; f_mem_r a transfer of a floating point register to a real reg via mem
-; r_mem_f the reverse of f_mem_r
-; f_2_r fast transfer float to arm (no memory needed)
-; r_2_f fast transfer arm to float
-; f_cvt convert floating<->integral
-; branch a branch
-; call a subroutine call
-; load_byte load byte(s) from memory to arm registers
-; load1 load 1 word from memory to arm registers
-; load2 load 2 words from memory to arm registers
-; load3 load 3 words from memory to arm registers
-; load4 load 4 words from memory to arm registers
-; store store 1 word to memory from arm registers
-; store2 store 2 words
-; store3 store 3 words
-; store4 store 4 (or more) words
-; Additions for Cirrus Maverick co-processor:
-; mav_farith Floating point arithmetic (4 cycle)
-; mav_dmult Double multiplies (7 cycle)
-;
-(define_attr "type"
- "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,f_flag,float_em,f_load,f_store,f_loads,f_loadd,f_stores,f_stored,f_mem_r,r_mem_f,f_2_r,r_2_f,f_cvt,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult"
- (if_then_else
- (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
- (const_string "mult")
- (const_string "alu")))
-
-; Load scheduling, set from the arm_ld_sched variable
-; initialized by arm_override_options()
-(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
-
-; condition codes: this one is used by final_prescan_insn to speed up
-; conditionalizing instructions. It saves having to scan the rtl to see if
-; it uses or alters the condition codes.
-;
-; USE means that the condition codes are used by the insn in the process of
-; outputting code, this means (at present) that we can't use the insn in
-; inlined branches
-;
-; SET means that the purpose of the insn is to set the condition codes in a
-; well defined manner.
-;
-; CLOB means that the condition codes are altered in an undefined manner, if
-; they are altered at all
-;
-; JUMP_CLOB is used when the condition cannot be represented by a single
-; instruction (UNEQ and LTGT). These cannot be predicated.
-;
-; NOCOND means that the condition codes are neither altered nor affect the
-; output of this insn
-
-(define_attr "conds" "use,set,clob,jump_clob,nocond"
- (if_then_else (eq_attr "type" "call")
- (const_string "clob")
- (const_string "nocond")))
-
-; Predicable means that the insn can be conditionally executed based on
-; an automatically added predicate (additional patterns are generated by
-; gen...). We default to 'no' because no Thumb patterns match this rule
-; and not all ARM patterns do.
-(define_attr "predicable" "no,yes" (const_string "no"))
-
-; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
-; have one. Later ones, such as StrongARM, have write-back caches, so don't
-; suffer blockages enough to warrant modelling this (and it can adversely
-; affect the schedule).
-(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
-
-; WRITE_CONFLICT implies that a read following an unrelated write is likely
-; to stall the processor. Used with model_wbuf above.
-(define_attr "write_conflict" "no,yes"
- (if_then_else (eq_attr "type"
- "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
- (const_string "yes")
- (const_string "no")))
-
-; Classify the insns into those that take one cycle and those that take more
-; than one on the main cpu execution unit.
-(define_attr "core_cycles" "single,multi"
- (if_then_else (eq_attr "type"
- "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
- (const_string "single")
- (const_string "multi")))
-
-;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
-;; distant label. Only applicable to Thumb code.
-(define_attr "far_jump" "yes,no" (const_string "no"))
-
-
-;;---------------------------------------------------------------------------
-;; Mode macros
-
-; A list of modes that are exactly 64 bits in size. We use this to expand
-; some splits that are the same for all modes when operating on ARM
-; registers.
-(define_mode_macro ANY64 [DI DF V8QI V4HI V2SI V2SF])
-
-;;---------------------------------------------------------------------------
-;; Predicates
-
-(include "predicates.md")
-(include "constraints.md")
-
-;;---------------------------------------------------------------------------
-;; Pipeline descriptions
-
-;; Processor type. This is created automatically from arm-cores.def.
-(include "arm-tune.md")
-
-;; True if the generic scheduling description should be used.
-
-(define_attr "generic_sched" "yes,no"
- (const (if_then_else
- (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs")
- (const_string "no")
- (const_string "yes"))))
-
-(define_attr "generic_vfp" "yes,no"
- (const (if_then_else
- (and (eq_attr "fpu" "vfp")
- (eq_attr "tune" "!arm1020e,arm1022e"))
- (const_string "yes")
- (const_string "no"))))
-
-(include "arm-generic.md")
-(include "arm926ejs.md")
-(include "arm1020e.md")
-(include "arm1026ejs.md")
-(include "arm1136jfs.md")
-
-
-;;---------------------------------------------------------------------------
-;; Insn patterns
-;;
-;; Addition insns.
-
-;; Note: For DImode insns, there is normally no reason why operands should
-;; not be in the same register, what we don't want is for something being
-;; written to partially overlap something that is an input.
-;; Cirrus 64bit additions should not be split because we have a native
-;; 64bit addition instructions.
-
-(define_expand "adddi3"
- [(parallel
- [(set (match_operand:DI 0 "s_register_operand" "")
- (plus:DI (match_operand:DI 1 "s_register_operand" "")
- (match_operand:DI 2 "s_register_operand" "")))
- (clobber (reg:CC CC_REGNUM))])]
- "TARGET_EITHER"
- "
- if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
- {
- if (!cirrus_fp_register (operands[0], DImode))
- operands[0] = force_reg (DImode, operands[0]);
- if (!cirrus_fp_register (operands[1], DImode))
- operands[1] = force_reg (DImode, operands[1]);
- emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
- DONE;
- }
-
- if (TARGET_THUMB)
- {
- if (GET_CODE (operands[1]) != REG)
- operands[1] = force_reg (SImode, operands[1]);
- if (GET_CODE (operands[2]) != REG)
- operands[2] = force_reg (SImode, operands[2]);
- }
- "
-)
-
-(define_insn "*thumb_adddi3"
- [(set (match_operand:DI 0 "register_operand" "=l")
- (plus:DI (match_operand:DI 1 "register_operand" "%0")
- (match_operand:DI 2 "register_operand" "l")))
- (clobber (reg:CC CC_REGNUM))
- ]
- "TARGET_THUMB"
- "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
- [(set_attr "length" "4")]
-)
-
-(define_insn_and_split "*arm_adddi3"
- [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
- (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
- (match_operand:DI 2 "s_register_operand" "r, 0")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
- "#"
- "TARGET_ARM && reload_completed"
- [(parallel [(set (reg:CC_C CC_REGNUM)
- (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
- (match_dup 1)))
- (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
- (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
- (plus:SI (match_dup 4) (match_dup 5))))]
- "
- {
- operands[3] = gen_highpart (SImode, operands[0]);
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[4] = gen_highpart (SImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- operands[5] = gen_highpart (SImode, operands[2]);
- operands[2] = gen_lowpart (SImode, operands[2]);
- }"
- [(set_attr "conds" "clob")
- (set_attr "length" "8")]
-)
-
-(define_insn_and_split "*adddi_sesidi_di"
- [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
- (plus:DI (sign_extend:DI
- (match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:DI 1 "s_register_operand" "r,0")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
- "#"
- "TARGET_ARM && reload_completed"
- [(parallel [(set (reg:CC_C CC_REGNUM)
- (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
- (match_dup 1)))
- (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
- (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
- (plus:SI (ashiftrt:SI (match_dup 2)
- (const_int 31))
- (match_dup 4))))]
- "
- {
- operands[3] = gen_highpart (SImode, operands[0]);
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[4] = gen_highpart (SImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = gen_lowpart (SImode, operands[2]);
- }"
- [(set_attr "conds" "clob")
- (set_attr "length" "8")]
-)
-
-(define_insn_and_split "*adddi_zesidi_di"
- [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
- (plus:DI (zero_extend:DI
- (match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:DI 1 "s_register_operand" "r,0")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
- "#"
- "TARGET_ARM && reload_completed"
- [(parallel [(set (reg:CC_C CC_REGNUM)
- (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
- (match_dup 1)))
- (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
- (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
- (plus:SI (match_dup 4) (const_int 0))))]
- "
- {
- operands[3] = gen_highpart (SImode, operands[0]);
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[4] = gen_highpart (SImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = gen_lowpart (SImode, operands[2]);
- }"
- [(set_attr "conds" "clob")
- (set_attr "length" "8")]
-)
-
-(define_expand "addsi3"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (plus:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "reg_or_int_operand" "")))]
- "TARGET_EITHER"
- "
- if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
- {
- arm_split_constant (PLUS, SImode, NULL_RTX,
- INTVAL (operands[2]), operands[0], operands[1],
- optimize && !no_new_pseudos);
- DONE;
- }
- "
-)
-
-; If there is a scratch available, this will be faster than synthesizing the
-; addition.
-(define_peephole2
- [(match_scratch:SI 3 "r")
- (set (match_operand:SI 0 "arm_general_register_operand" "")
- (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
- (match_operand:SI 2 "const_int_operand" "")))]
- "TARGET_ARM &&
- !(const_ok_for_arm (INTVAL (operands[2]))
- || const_ok_for_arm (-INTVAL (operands[2])))
- && const_ok_for_arm (~INTVAL (operands[2]))"
- [(set (match_dup 3) (match_dup 2))
- (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
- ""
-)
-
-(define_insn_and_split "*arm_addsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
- (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
- (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
- "TARGET_ARM"
- "@
- add%?\\t%0, %1, %2
- sub%?\\t%0, %1, #%n2
- #"
- "TARGET_ARM &&
- GET_CODE (operands[2]) == CONST_INT
- && !(const_ok_for_arm (INTVAL (operands[2]))
- || const_ok_for_arm (-INTVAL (operands[2])))"
- [(clobber (const_int 0))]
- "
- arm_split_constant (PLUS, SImode, curr_insn,
- INTVAL (operands[2]), operands[0],
- operands[1], 0);
- DONE;
- "
- [(set_attr "length" "4,4,16")
- (set_attr "predicable" "yes")]
-)
-
-;; 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 "*thumb_addsi3"
- [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
- (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
- (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
- "TARGET_THUMB"
- "*
- static const char * const 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 || which_alternative == 6)
- && GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) < 0)
- return \"sub\\t%0, %1, #%n2\";
- return asms[which_alternative];
- "
- [(set_attr "length" "2")]
-)
-
-;; Reloading and elimination of the frame pointer can
-;; sometimes cause this optimization to be missed.
-(define_peephole2
- [(set (match_operand:SI 0 "arm_general_register_operand" "")
- (match_operand:SI 1 "const_int_operand" ""))
- (set (match_dup 0)
- (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
- "TARGET_THUMB
- && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
- && (INTVAL (operands[1]) & 3) == 0"
- [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
- ""
-)
-
-(define_insn "*addsi3_compare0"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV
- (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
- (match_operand:SI 2 "arm_add_operand" "rI,L"))
- (const_int 0)))
- (set (match_operand:SI 0 "s_register_operand" "=r,r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM"
- "@
- add%?s\\t%0, %1, %2
- sub%?s\\t%0, %1, #%n2"
- [(set_attr "conds" "set")]
-)
-
-(define_insn "*addsi3_compare0_scratch"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV
- (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
- (match_operand:SI 1 "arm_add_operand" "rI,L"))
- (const_int 0)))]
- "TARGET_ARM"
- "@
- cmn%?\\t%0, %1
- cmp%?\\t%0, #%n1"
- [(set_attr "conds" "set")]
-)
-
-(define_insn "*compare_negsi_si"
- [(set (reg:CC_Z CC_REGNUM)
- (compare:CC_Z
- (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
- (match_operand:SI 1 "s_register_operand" "r")))]
- "TARGET_ARM"
- "cmn%?\\t%1, %0"
- [(set_attr "conds" "set")]
-)
-
-;; This is the canonicalization of addsi3_compare0_for_combiner when the
-;; addend is a constant.
-(define_insn "*cmpsi2_addneg"
- [(set (reg:CC CC_REGNUM)
- (compare:CC
- (match_operand:SI 1 "s_register_operand" "r,r")
- (match_operand:SI 2 "arm_addimm_operand" "I,L")))
- (set (match_operand:SI 0 "s_register_operand" "=r,r")
- (plus:SI (match_dup 1)
- (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
- "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
- "@
- sub%?s\\t%0, %1, %2
- add%?s\\t%0, %1, #%n2"
- [(set_attr "conds" "set")]
-)
-
-;; Convert the sequence
-;; sub rd, rn, #1
-;; cmn rd, #1 (equivalent to cmp rd, #-1)
-;; bne dest
-;; into
-;; subs rd, rn, #1
-;; bcs dest ((unsigned)rn >= 1)
-;; similarly for the beq variant using bcc.
-;; This is a common looping idiom (while (n--))
-(define_peephole2
- [(set (match_operand:SI 0 "arm_general_register_operand" "")
- (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
- (const_int -1)))
- (set (match_operand 2 "cc_register" "")
- (compare (match_dup 0) (const_int -1)))
- (set (pc)
- (if_then_else (match_operator 3 "equality_operator"
- [(match_dup 2) (const_int 0)])
- (match_operand 4 "" "")
- (match_operand 5 "" "")))]
- "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
- [(parallel[
- (set (match_dup 2)
- (compare:CC
- (match_dup 1) (const_int 1)))
- (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
- (set (pc)
- (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
- (match_dup 4)
- (match_dup 5)))]
- "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
- operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
- ? GEU : LTU),
- VOIDmode,
- operands[2], const0_rtx);"
-)
-
-;; The next four insns work because they compare the result with one of
-;; the operands, and we know that the use of the condition code is
-;; either GEU or LTU, so we can use the carry flag from the addition
-;; instead of doing the compare a second time.
-(define_insn "*addsi3_compare_op1"
- [(set (reg:CC_C CC_REGNUM)
- (compare:CC_C
- (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
- (match_operand:SI 2 "arm_add_operand" "rI,L"))
- (match_dup 1)))
- (set (match_operand:SI 0 "s_register_operand" "=r,r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM"
- "@
- add%?s\\t%0, %1, %2
- sub%?s\\t%0, %1, #%n2"
- [(set_attr "conds" "set")]
-)
-
-(define_insn "*addsi3_compare_op2"
- [(set (reg:CC_C CC_REGNUM)
- (compare:CC_C
- (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
- (match_operand:SI 2 "arm_add_operand" "rI,L"))
- (match_dup 2)))
- (set (match_operand:SI 0 "s_register_operand" "=r,r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM"
- "@
- add%?s\\t%0, %1, %2
- sub%?s\\t%0, %1, #%n2"
- [(set_attr "conds" "set")]
-)
-
-(define_insn "*compare_addsi2_op0"
- [(set (reg:CC_C CC_REGNUM)
- (compare:CC_C
- (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
- (match_operand:SI 1 "arm_add_operand" "rI,L"))
- (match_dup 0)))]
- "TARGET_ARM"
- "@
- cmn%?\\t%0, %1
- cmp%?\\t%0, #%n1"
- [(set_attr "conds" "set")]
-)
-
-(define_insn "*compare_addsi2_op1"
- [(set (reg:CC_C CC_REGNUM)
- (compare:CC_C
- (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
- (match_operand:SI 1 "arm_add_operand" "rI,L"))
- (match_dup 1)))]
- "TARGET_ARM"
- "@
- cmn%?\\t%0, %1
- cmp%?\\t%0, #%n1"
- [(set_attr "conds" "set")]
-)
-
-(define_insn "*addsi3_carryin"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
- (plus:SI (match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
- "TARGET_ARM"
- "adc%?\\t%0, %1, %2"
- [(set_attr "conds" "use")]
-)
-
-(define_insn "*addsi3_carryin_shift"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
- (plus:SI
- (match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "reg_or_int_operand" "rM")])
- (match_operand:SI 1 "s_register_operand" "r"))))]
- "TARGET_ARM"
- "adc%?\\t%0, %1, %3%S2"
- [(set_attr "conds" "use")
- (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
- (const_string "alu_shift")
- (const_string "alu_shift_reg")))]
-)
-
-(define_insn "*addsi3_carryin_alt1"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "arm_rhs_operand" "rI"))
- (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
- "TARGET_ARM"
- "adc%?\\t%0, %1, %2"
- [(set_attr "conds" "use")]
-)
-
-(define_insn "*addsi3_carryin_alt2"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
- (match_operand:SI 1 "s_register_operand" "r"))
- (match_operand:SI 2 "arm_rhs_operand" "rI")))]
- "TARGET_ARM"
- "adc%?\\t%0, %1, %2"
- [(set_attr "conds" "use")]
-)
-
-(define_insn "*addsi3_carryin_alt3"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
- (match_operand:SI 2 "arm_rhs_operand" "rI"))
- (match_operand:SI 1 "s_register_operand" "r")))]
- "TARGET_ARM"
- "adc%?\\t%0, %1, %2"
- [(set_attr "conds" "use")]
-)
-
-(define_insn "incscc"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (plus:SI (match_operator:SI 2 "arm_comparison_operator"
- [(match_operand:CC 3 "cc_register" "") (const_int 0)])
- (match_operand:SI 1 "s_register_operand" "0,?r")))]
- "TARGET_ARM"
- "@
- add%d2\\t%0, %1, #1
- mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
- [(set_attr "conds" "use")
- (set_attr "length" "4,8")]
-)
-
-; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
-(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
- (match_operand:SI 2 "s_register_operand" ""))
- (const_int -1)))
- (clobber (match_operand:SI 3 "s_register_operand" ""))]
- "TARGET_ARM"
- [(set (match_dup 3) (match_dup 1))
- (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
- "
- operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
-")
-
-(define_expand "addsf3"
- [(set (match_operand:SF 0 "s_register_operand" "")
- (plus:SF (match_operand:SF 1 "s_register_operand" "")
- (match_operand:SF 2 "arm_float_add_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "
- if (TARGET_MAVERICK
- && !cirrus_fp_register (operands[2], SFmode))
- operands[2] = force_reg (SFmode, operands[2]);
-")
-
-(define_expand "adddf3"
- [(set (match_operand:DF 0 "s_register_operand" "")
- (plus:DF (match_operand:DF 1 "s_register_operand" "")
- (match_operand:DF 2 "arm_float_add_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "
- if (TARGET_MAVERICK
- && !cirrus_fp_register (operands[2], DFmode))
- operands[2] = force_reg (DFmode, operands[2]);
-")
-
-(define_expand "subdi3"
- [(parallel
- [(set (match_operand:DI 0 "s_register_operand" "")
- (minus:DI (match_operand:DI 1 "s_register_operand" "")
- (match_operand:DI 2 "s_register_operand" "")))
- (clobber (reg:CC CC_REGNUM))])]
- "TARGET_EITHER"
- "
- if (TARGET_HARD_FLOAT && TARGET_MAVERICK
- && TARGET_ARM
- && cirrus_fp_register (operands[0], DImode)
- && cirrus_fp_register (operands[1], DImode))
- {
- emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
- DONE;
- }
-
- if (TARGET_THUMB)
- {
- if (GET_CODE (operands[1]) != REG)
- operands[1] = force_reg (SImode, operands[1]);
- if (GET_CODE (operands[2]) != REG)
- operands[2] = force_reg (SImode, operands[2]);
- }
- "
-)
-
-(define_insn "*arm_subdi3"
- [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
- (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
- (match_operand:DI 2 "s_register_operand" "r,0,0")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
- [(set_attr "conds" "clob")
- (set_attr "length" "8")]
-)
-
-(define_insn "*thumb_subdi3"
- [(set (match_operand:DI 0 "register_operand" "=l")
- (minus:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:DI 2 "register_operand" "l")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_THUMB"
- "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
- [(set_attr "length" "4")]
-)
-
-(define_insn "*subdi_di_zesidi"
- [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
- (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
- (zero_extend:DI
- (match_operand:SI 2 "s_register_operand" "r,r"))))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
- [(set_attr "conds" "clob")
- (set_attr "length" "8")]
-)
-
-(define_insn "*subdi_di_sesidi"
- [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
- (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
- (sign_extend:DI
- (match_operand:SI 2 "s_register_operand" "r,r"))))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
- [(set_attr "conds" "clob")
- (set_attr "length" "8")]
-)
-
-(define_insn "*subdi_zesidi_di"
- [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
- (minus:DI (zero_extend:DI
- (match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:DI 1 "s_register_operand" "?r,0")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
- [(set_attr "conds" "clob")
- (set_attr "length" "8")]
-)
-
-(define_insn "*subdi_sesidi_di"
- [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
- (minus:DI (sign_extend:DI
- (match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:DI 1 "s_register_operand" "?r,0")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
- [(set_attr "conds" "clob")
- (set_attr "length" "8")]
-)
-
-(define_insn "*subdi_zesidi_zesidi"
- [(set (match_operand:DI 0 "s_register_operand" "=r")
- (minus:DI (zero_extend:DI
- (match_operand:SI 1 "s_register_operand" "r"))
- (zero_extend:DI
- (match_operand:SI 2 "s_register_operand" "r"))))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
- [(set_attr "conds" "clob")
- (set_attr "length" "8")]
-)
-
-(define_expand "subsi3"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
- (match_operand:SI 2 "s_register_operand" "")))]
- "TARGET_EITHER"
- "
- if (GET_CODE (operands[1]) == CONST_INT)
- {
- if (TARGET_ARM)
- {
- arm_split_constant (MINUS, SImode, NULL_RTX,
- INTVAL (operands[1]), operands[0],
- operands[2], optimize && !no_new_pseudos);
- DONE;
- }
- else /* TARGET_THUMB */
- operands[1] = force_reg (SImode, operands[1]);
- }
- "
-)
-
-(define_insn "*thumb_subsi3_insn"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (minus:SI (match_operand:SI 1 "register_operand" "l")
- (match_operand:SI 2 "register_operand" "l")))]
- "TARGET_THUMB"
- "sub\\t%0, %1, %2"
- [(set_attr "length" "2")]
-)
-
-(define_insn_and_split "*arm_subsi3_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
- (match_operand:SI 2 "s_register_operand" "r,r")))]
- "TARGET_ARM"
- "@
- rsb%?\\t%0, %2, %1
- #"
- "TARGET_ARM
- && GET_CODE (operands[1]) == CONST_INT
- && !const_ok_for_arm (INTVAL (operands[1]))"
- [(clobber (const_int 0))]
- "
- arm_split_constant (MINUS, SImode, curr_insn,
- INTVAL (operands[1]), operands[0], operands[2], 0);
- DONE;
- "
- [(set_attr "length" "4,16")
- (set_attr "predicable" "yes")]
-)
-
-(define_peephole2
- [(match_scratch:SI 3 "r")
- (set (match_operand:SI 0 "arm_general_register_operand" "")
- (minus:SI (match_operand:SI 1 "const_int_operand" "")
- (match_operand:SI 2 "arm_general_register_operand" "")))]
- "TARGET_ARM
- && !const_ok_for_arm (INTVAL (operands[1]))
- && const_ok_for_arm (~INTVAL (operands[1]))"
- [(set (match_dup 3) (match_dup 1))
- (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
- ""
-)
-
-(define_insn "*subsi3_compare0"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV
- (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
- (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
- (const_int 0)))
- (set (match_operand:SI 0 "s_register_operand" "=r,r")
- (minus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM"
- "@
- sub%?s\\t%0, %1, %2
- rsb%?s\\t%0, %2, %1"
- [(set_attr "conds" "set")]
-)
-
-(define_insn "decscc"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
- (match_operator:SI 2 "arm_comparison_operator"
- [(match_operand 3 "cc_register" "") (const_int 0)])))]
- "TARGET_ARM"
- "@
- sub%d2\\t%0, %1, #1
- mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
- [(set_attr "conds" "use")
- (set_attr "length" "*,8")]
-)
-
-(define_expand "subsf3"
- [(set (match_operand:SF 0 "s_register_operand" "")
- (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
- (match_operand:SF 2 "arm_float_rhs_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "
- if (TARGET_MAVERICK)
- {
- if (!cirrus_fp_register (operands[1], SFmode))
- operands[1] = force_reg (SFmode, operands[1]);
- if (!cirrus_fp_register (operands[2], SFmode))
- operands[2] = force_reg (SFmode, operands[2]);
- }
-")
-
-(define_expand "subdf3"
- [(set (match_operand:DF 0 "s_register_operand" "")
- (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
- (match_operand:DF 2 "arm_float_rhs_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "
- if (TARGET_MAVERICK)
- {
- if (!cirrus_fp_register (operands[1], DFmode))
- operands[1] = force_reg (DFmode, operands[1]);
- if (!cirrus_fp_register (operands[2], DFmode))
- operands[2] = force_reg (DFmode, operands[2]);
- }
-")
-
-
-;; Multiplication insns
-
-(define_expand "mulsi3"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (mult:SI (match_operand:SI 2 "s_register_operand" "")
- (match_operand:SI 1 "s_register_operand" "")))]
- "TARGET_EITHER"
- ""
-)
-
-;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
-(define_insn "*arm_mulsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
- (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
- (match_operand:SI 1 "s_register_operand" "%?r,0")))]
- "TARGET_ARM"
- "mul%?\\t%0, %2, %1"
- [(set_attr "insn" "mul")
- (set_attr "predicable" "yes")]
-)
-
-; Unfortunately with the Thumb the '&'/'0' trick can 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 "*thumb_mulsi3"
- [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
- (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
- (match_operand:SI 2 "register_operand" "l,l,l")))]
- "TARGET_THUMB"
- "*
- if (which_alternative < 2)
- return \"mov\\t%0, %1\;mul\\t%0, %2\";
- else
- return \"mul\\t%0, %2\";
- "
- [(set_attr "length" "4,4,2")
- (set_attr "insn" "mul")]
-)
-
-(define_insn "*mulsi3_compare0"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (mult:SI
- (match_operand:SI 2 "s_register_operand" "r,r")
- (match_operand:SI 1 "s_register_operand" "%?r,0"))
- (const_int 0)))
- (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
- (mult:SI (match_dup 2) (match_dup 1)))]
- "TARGET_ARM"
- "mul%?s\\t%0, %2, %1"
- [(set_attr "conds" "set")
- (set_attr "insn" "muls")]
-)
-
-(define_insn "*mulsi_compare0_scratch"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (mult:SI
- (match_operand:SI 2 "s_register_operand" "r,r")
- (match_operand:SI 1 "s_register_operand" "%?r,0"))
- (const_int 0)))
- (clobber (match_scratch:SI 0 "=&r,&r"))]
- "TARGET_ARM"
- "mul%?s\\t%0, %2, %1"
- [(set_attr "conds" "set")
- (set_attr "insn" "muls")]
-)
-
-;; Unnamed templates to match MLA instruction.
-
-(define_insn "*mulsi3addsi"
- [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
- (plus:SI
- (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
- (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
- (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
- "TARGET_ARM"
- "mla%?\\t%0, %2, %1, %3"
- [(set_attr "insn" "mla")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*mulsi3addsi_compare0"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV
- (plus:SI (mult:SI
- (match_operand:SI 2 "s_register_operand" "r,r,r,r")
- (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
- (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
- (const_int 0)))
- (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
- (plus:SI (mult:SI (match_dup 2) (match_dup 1))
- (match_dup 3)))]
- "TARGET_ARM"
- "mla%?s\\t%0, %2, %1, %3"
- [(set_attr "conds" "set")
- (set_attr "insn" "mlas")]
-)
-
-(define_insn "*mulsi3addsi_compare0_scratch"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV
- (plus:SI (mult:SI
- (match_operand:SI 2 "s_register_operand" "r,r,r,r")
- (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
- (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
- (const_int 0)))
- (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
- "TARGET_ARM"
- "mla%?s\\t%0, %2, %1, %3"
- [(set_attr "conds" "set")
- (set_attr "insn" "mlas")]
-)
-
-;; Unnamed template to match long long multiply-accumulate (smlal)
-
-(define_insn "*mulsidi3adddi"
- [(set (match_operand:DI 0 "s_register_operand" "=&r")
- (plus:DI
- (mult:DI
- (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
- (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
- (match_operand:DI 1 "s_register_operand" "0")))]
- "TARGET_ARM && arm_arch3m"
- "smlal%?\\t%Q0, %R0, %3, %2"
- [(set_attr "insn" "smlal")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "mulsidi3"
- [(set (match_operand:DI 0 "s_register_operand" "=&r")
- (mult:DI
- (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
- (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
- "TARGET_ARM && arm_arch3m"
- "smull%?\\t%Q0, %R0, %1, %2"
- [(set_attr "insn" "smull")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "umulsidi3"
- [(set (match_operand:DI 0 "s_register_operand" "=&r")
- (mult:DI
- (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
- (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
- "TARGET_ARM && arm_arch3m"
- "umull%?\\t%Q0, %R0, %1, %2"
- [(set_attr "insn" "umull")
- (set_attr "predicable" "yes")]
-)
-
-;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
-
-(define_insn "*umulsidi3adddi"
- [(set (match_operand:DI 0 "s_register_operand" "=&r")
- (plus:DI
- (mult:DI
- (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
- (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
- (match_operand:DI 1 "s_register_operand" "0")))]
- "TARGET_ARM && arm_arch3m"
- "umlal%?\\t%Q0, %R0, %3, %2"
- [(set_attr "insn" "umlal")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "smulsi3_highpart"
- [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
- (truncate:SI
- (lshiftrt:DI
- (mult:DI
- (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
- (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
- (const_int 32))))
- (clobber (match_scratch:SI 3 "=&r,&r"))]
- "TARGET_ARM && arm_arch3m"
- "smull%?\\t%3, %0, %2, %1"
- [(set_attr "insn" "smull")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "umulsi3_highpart"
- [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
- (truncate:SI
- (lshiftrt:DI
- (mult:DI
- (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
- (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
- (const_int 32))))
- (clobber (match_scratch:SI 3 "=&r,&r"))]
- "TARGET_ARM && arm_arch3m"
- "umull%?\\t%3, %0, %2, %1"
- [(set_attr "insn" "umull")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "mulhisi3"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (mult:SI (sign_extend:SI
- (match_operand:HI 1 "s_register_operand" "%r"))
- (sign_extend:SI
- (match_operand:HI 2 "s_register_operand" "r"))))]
- "TARGET_ARM && arm_arch5e"
- "smulbb%?\\t%0, %1, %2"
- [(set_attr "insn" "smulxy")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*mulhisi3tb"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (mult:SI (ashiftrt:SI
- (match_operand:SI 1 "s_register_operand" "r")
- (const_int 16))
- (sign_extend:SI
- (match_operand:HI 2 "s_register_operand" "r"))))]
- "TARGET_ARM && arm_arch5e"
- "smultb%?\\t%0, %1, %2"
- [(set_attr "insn" "smulxy")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*mulhisi3bt"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (mult:SI (sign_extend:SI
- (match_operand:HI 1 "s_register_operand" "r"))
- (ashiftrt:SI
- (match_operand:SI 2 "s_register_operand" "r")
- (const_int 16))))]
- "TARGET_ARM && arm_arch5e"
- "smulbt%?\\t%0, %1, %2"
- [(set_attr "insn" "smulxy")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*mulhisi3tt"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (mult:SI (ashiftrt:SI
- (match_operand:SI 1 "s_register_operand" "r")
- (const_int 16))
- (ashiftrt:SI
- (match_operand:SI 2 "s_register_operand" "r")
- (const_int 16))))]
- "TARGET_ARM && arm_arch5e"
- "smultt%?\\t%0, %1, %2"
- [(set_attr "insn" "smulxy")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*mulhisi3addsi"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (match_operand:SI 1 "s_register_operand" "r")
- (mult:SI (sign_extend:SI
- (match_operand:HI 2 "s_register_operand" "%r"))
- (sign_extend:SI
- (match_operand:HI 3 "s_register_operand" "r")))))]
- "TARGET_ARM && arm_arch5e"
- "smlabb%?\\t%0, %2, %3, %1"
- [(set_attr "insn" "smlaxy")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*mulhidi3adddi"
- [(set (match_operand:DI 0 "s_register_operand" "=r")
- (plus:DI
- (match_operand:DI 1 "s_register_operand" "0")
- (mult:DI (sign_extend:DI
- (match_operand:HI 2 "s_register_operand" "%r"))
- (sign_extend:DI
- (match_operand:HI 3 "s_register_operand" "r")))))]
- "TARGET_ARM && arm_arch5e"
- "smlalbb%?\\t%Q0, %R0, %2, %3"
- [(set_attr "insn" "smlalxy")
- (set_attr "predicable" "yes")])
-
-(define_expand "mulsf3"
- [(set (match_operand:SF 0 "s_register_operand" "")
- (mult:SF (match_operand:SF 1 "s_register_operand" "")
- (match_operand:SF 2 "arm_float_rhs_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "
- if (TARGET_MAVERICK
- && !cirrus_fp_register (operands[2], SFmode))
- operands[2] = force_reg (SFmode, operands[2]);
-")
-
-(define_expand "muldf3"
- [(set (match_operand:DF 0 "s_register_operand" "")
- (mult:DF (match_operand:DF 1 "s_register_operand" "")
- (match_operand:DF 2 "arm_float_rhs_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "
- if (TARGET_MAVERICK
- && !cirrus_fp_register (operands[2], DFmode))
- operands[2] = force_reg (DFmode, operands[2]);
-")
-
-;; Division insns
-
-(define_expand "divsf3"
- [(set (match_operand:SF 0 "s_register_operand" "")
- (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
- (match_operand:SF 2 "arm_float_rhs_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "")
-
-(define_expand "divdf3"
- [(set (match_operand:DF 0 "s_register_operand" "")
- (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
- (match_operand:DF 2 "arm_float_rhs_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "")
-
-;; Modulo insns
-
-(define_expand "modsf3"
- [(set (match_operand:SF 0 "s_register_operand" "")
- (mod:SF (match_operand:SF 1 "s_register_operand" "")
- (match_operand:SF 2 "arm_float_rhs_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "")
-
-(define_expand "moddf3"
- [(set (match_operand:DF 0 "s_register_operand" "")
- (mod:DF (match_operand:DF 1 "s_register_operand" "")
- (match_operand:DF 2 "arm_float_rhs_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "")
-
-;; Boolean and,ior,xor insns
-
-;; Split up double word logical operations
-
-;; Split up simple DImode logical operations. Simply perform the logical
-;; operation on the upper and lower halves of the registers.
-(define_split
- [(set (match_operand:DI 0 "s_register_operand" "")
- (match_operator:DI 6 "logical_binary_operator"
- [(match_operand:DI 1 "s_register_operand" "")
- (match_operand:DI 2 "s_register_operand" "")]))]
- "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
- [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
- (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
- "
- {
- operands[3] = gen_highpart (SImode, operands[0]);
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[4] = gen_highpart (SImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- operands[5] = gen_highpart (SImode, operands[2]);
- operands[2] = gen_lowpart (SImode, operands[2]);
- }"
-)
-
-(define_split
- [(set (match_operand:DI 0 "s_register_operand" "")
- (match_operator:DI 6 "logical_binary_operator"
- [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
- (match_operand:DI 1 "s_register_operand" "")]))]
- "TARGET_ARM && reload_completed"
- [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
- (set (match_dup 3) (match_op_dup:SI 6
- [(ashiftrt:SI (match_dup 2) (const_int 31))
- (match_dup 4)]))]
- "
- {
- operands[3] = gen_highpart (SImode, operands[0]);
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[4] = gen_highpart (SImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- operands[5] = gen_highpart (SImode, operands[2]);
- operands[2] = gen_lowpart (SImode, operands[2]);
- }"
-)
-
-;; The zero extend of operand 2 means we can just copy the high part of
-;; operand1 into operand0.
-(define_split
- [(set (match_operand:DI 0 "s_register_operand" "")
- (ior:DI
- (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
- (match_operand:DI 1 "s_register_operand" "")))]
- "TARGET_ARM && operands[0] != operands[1] && reload_completed"
- [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
- (set (match_dup 3) (match_dup 4))]
- "
- {
- operands[4] = gen_highpart (SImode, operands[1]);
- operands[3] = gen_highpart (SImode, operands[0]);
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- }"
-)
-
-;; The zero extend of operand 2 means we can just copy the high part of
-;; operand1 into operand0.
-(define_split
- [(set (match_operand:DI 0 "s_register_operand" "")
- (xor:DI
- (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
- (match_operand:DI 1 "s_register_operand" "")))]
- "TARGET_ARM && operands[0] != operands[1] && reload_completed"
- [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
- (set (match_dup 3) (match_dup 4))]
- "
- {
- operands[4] = gen_highpart (SImode, operands[1]);
- operands[3] = gen_highpart (SImode, operands[0]);
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- }"
-)
-
-(define_insn "anddi3"
- [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
- (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
- (match_operand:DI 2 "s_register_operand" "r,r")))]
- "TARGET_ARM && ! TARGET_IWMMXT"
- "#"
- [(set_attr "length" "8")]
-)
-
-(define_insn_and_split "*anddi_zesidi_di"
- [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
- (and:DI (zero_extend:DI
- (match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:DI 1 "s_register_operand" "?r,0")))]
- "TARGET_ARM"
- "#"
- "TARGET_ARM && reload_completed"
- ; The zero extend of operand 2 clears the high word of the output
- ; operand.
- [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
- (set (match_dup 3) (const_int 0))]
- "
- {
- operands[3] = gen_highpart (SImode, operands[0]);
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- }"
- [(set_attr "length" "8")]
-)
-
-(define_insn "*anddi_sesdi_di"
- [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
- (and:DI (sign_extend:DI
- (match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:DI 1 "s_register_operand" "?r,0")))]
- "TARGET_ARM"
- "#"
- [(set_attr "length" "8")]
-)
-
-(define_expand "andsi3"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (and:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "reg_or_int_operand" "")))]
- "TARGET_EITHER"
- "
- if (TARGET_ARM)
- {
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- arm_split_constant (AND, SImode, NULL_RTX,
- INTVAL (operands[2]), operands[0],
- operands[1], optimize && !no_new_pseudos);
-
- DONE;
- }
- }
- else /* TARGET_THUMB */
- {
- if (GET_CODE (operands[2]) != CONST_INT)
- operands[2] = force_reg (SImode, operands[2]);
- else
- {
- int i;
-
- if (((unsigned HOST_WIDE_INT) ~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_and_split "*arm_andsi3_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
- (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
- (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
- "TARGET_ARM"
- "@
- and%?\\t%0, %1, %2
- bic%?\\t%0, %1, #%B2
- #"
- "TARGET_ARM
- && GET_CODE (operands[2]) == CONST_INT
- && !(const_ok_for_arm (INTVAL (operands[2]))
- || const_ok_for_arm (~INTVAL (operands[2])))"
- [(clobber (const_int 0))]
- "
- arm_split_constant (AND, SImode, curr_insn,
- INTVAL (operands[2]), operands[0], operands[1], 0);
- DONE;
- "
- [(set_attr "length" "4,4,16")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*thumb_andsi3_insn"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (and:SI (match_operand:SI 1 "register_operand" "%0")
- (match_operand:SI 2 "register_operand" "l")))]
- "TARGET_THUMB"
- "and\\t%0, %0, %2"
- [(set_attr "length" "2")]
-)
-
-(define_insn "*andsi3_compare0"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV
- (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
- (match_operand:SI 2 "arm_not_operand" "rI,K"))
- (const_int 0)))
- (set (match_operand:SI 0 "s_register_operand" "=r,r")
- (and:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM"
- "@
- and%?s\\t%0, %1, %2
- bic%?s\\t%0, %1, #%B2"
- [(set_attr "conds" "set")]
-)
-
-(define_insn "*andsi3_compare0_scratch"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV
- (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
- (match_operand:SI 1 "arm_not_operand" "rI,K"))
- (const_int 0)))
- (clobber (match_scratch:SI 2 "=X,r"))]
- "TARGET_ARM"
- "@
- tst%?\\t%0, %1
- bic%?s\\t%2, %0, #%B1"
- [(set_attr "conds" "set")]
-)
-
-(define_insn "*zeroextractsi_compare0_scratch"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (zero_extract:SI
- (match_operand:SI 0 "s_register_operand" "r")
- (match_operand 1 "const_int_operand" "n")
- (match_operand 2 "const_int_operand" "n"))
- (const_int 0)))]
- "TARGET_ARM
- && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
- && INTVAL (operands[1]) > 0
- && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
- && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
- "*
- operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
- << INTVAL (operands[2]));
- output_asm_insn (\"tst%?\\t%0, %1\", operands);
- return \"\";
- "
- [(set_attr "conds" "set")]
-)
-
-(define_insn_and_split "*ne_zeroextractsi"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (ne:SI (zero_extract:SI
- (match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "const_int_operand" "n")
- (match_operand:SI 3 "const_int_operand" "n"))
- (const_int 0)))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM
- && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
- && INTVAL (operands[2]) > 0
- && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
- && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
- "#"
- "TARGET_ARM
- && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
- && INTVAL (operands[2]) > 0
- && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
- && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
- [(parallel [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
- (const_int 0)))
- (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
- (set (match_dup 0)
- (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
- (match_dup 0) (const_int 1)))]
- "
- operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
- << INTVAL (operands[3]));
- "
- [(set_attr "conds" "clob")
- (set_attr "length" "8")]
-)
-
-(define_insn_and_split "*ne_zeroextractsi_shifted"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (ne:SI (zero_extract:SI
- (match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "const_int_operand" "n")
- (const_int 0))
- (const_int 0)))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "#"
- "TARGET_ARM"
- [(parallel [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
- (const_int 0)))
- (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
- (set (match_dup 0)
- (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
- (match_dup 0) (const_int 1)))]
- "
- operands[2] = GEN_INT (32 - INTVAL (operands[2]));
- "
- [(set_attr "conds" "clob")
- (set_attr "length" "8")]
-)
-
-(define_insn_and_split "*ite_ne_zeroextractsi"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (if_then_else:SI (ne (zero_extract:SI
- (match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "const_int_operand" "n")
- (match_operand:SI 3 "const_int_operand" "n"))
- (const_int 0))
- (match_operand:SI 4 "arm_not_operand" "rIK")
- (const_int 0)))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM
- && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
- && INTVAL (operands[2]) > 0
- && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
- && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
- && !reg_overlap_mentioned_p (operands[0], operands[4])"
- "#"
- "TARGET_ARM
- && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
- && INTVAL (operands[2]) > 0
- && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
- && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
- && !reg_overlap_mentioned_p (operands[0], operands[4])"
- [(parallel [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
- (const_int 0)))
- (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
- (set (match_dup 0)
- (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
- (match_dup 0) (match_dup 4)))]
- "
- operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
- << INTVAL (operands[3]));
- "
- [(set_attr "conds" "clob")
- (set_attr "length" "8")]
-)
-
-(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (if_then_else:SI (ne (zero_extract:SI
- (match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "const_int_operand" "n")
- (const_int 0))
- (const_int 0))
- (match_operand:SI 3 "arm_not_operand" "rIK")
- (const_int 0)))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
- "#"
- "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
- [(parallel [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
- (const_int 0)))
- (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
- (set (match_dup 0)
- (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
- (match_dup 0) (match_dup 3)))]
- "
- operands[2] = GEN_INT (32 - INTVAL (operands[2]));
- "
- [(set_attr "conds" "clob")
- (set_attr "length" "8")]
-)
-
-(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "const_int_operand" "")
- (match_operand:SI 3 "const_int_operand" "")))
- (clobber (match_operand:SI 4 "s_register_operand" ""))]
- "TARGET_THUMB"
- [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
- (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
- "{
- HOST_WIDE_INT temp = INTVAL (operands[2]);
-
- operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
- operands[3] = GEN_INT (32 - temp);
- }"
-)
-
-(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (match_operator:SI 1 "shiftable_operator"
- [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
- (match_operand:SI 3 "const_int_operand" "")
- (match_operand:SI 4 "const_int_operand" ""))
- (match_operand:SI 5 "s_register_operand" "")]))
- (clobber (match_operand:SI 6 "s_register_operand" ""))]
- "TARGET_ARM"
- [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
- (set (match_dup 0)
- (match_op_dup 1
- [(lshiftrt:SI (match_dup 6) (match_dup 4))
- (match_dup 5)]))]
- "{
- HOST_WIDE_INT temp = INTVAL (operands[3]);
-
- operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
- operands[4] = GEN_INT (32 - temp);
- }"
-)
-
-(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "const_int_operand" "")
- (match_operand:SI 3 "const_int_operand" "")))]
- "TARGET_THUMB"
- [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
- (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
- "{
- HOST_WIDE_INT temp = INTVAL (operands[2]);
-
- operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
- operands[3] = GEN_INT (32 - temp);
- }"
-)
-
-(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (match_operator:SI 1 "shiftable_operator"
- [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
- (match_operand:SI 3 "const_int_operand" "")
- (match_operand:SI 4 "const_int_operand" ""))
- (match_operand:SI 5 "s_register_operand" "")]))
- (clobber (match_operand:SI 6 "s_register_operand" ""))]
- "TARGET_ARM"
- [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
- (set (match_dup 0)
- (match_op_dup 1
- [(ashiftrt:SI (match_dup 6) (match_dup 4))
- (match_dup 5)]))]
- "{
- HOST_WIDE_INT temp = INTVAL (operands[3]);
-
- operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
- operands[4] = GEN_INT (32 - temp);
- }"
-)
-
-;;; ??? This pattern is bogus. If operand3 has bits outside the range
-;;; represented by the bitfield, then this will produce incorrect results.
-;;; Somewhere, the value needs to be truncated. On targets like the m68k,
-;;; which have a real bit-field insert instruction, the truncation happens
-;;; in the bit-field insert instruction itself. Since arm does not have a
-;;; bit-field insert instruction, we would have to emit code here to truncate
-;;; the value before we insert. This loses some of the advantage of having
-;;; this insv pattern, so this pattern needs to be reevalutated.
-
-(define_expand "insv"
- [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
- (match_operand:SI 1 "general_operand" "")
- (match_operand:SI 2 "general_operand" ""))
- (match_operand:SI 3 "reg_or_int_operand" ""))]
- "TARGET_ARM"
- "
- {
- int start_bit = INTVAL (operands[2]);
- int width = INTVAL (operands[1]);
- HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
- rtx target, subtarget;
-
- target = operands[0];
- /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
- subreg as the final target. */
- if (GET_CODE (target) == SUBREG)
- {
- subtarget = gen_reg_rtx (SImode);
- if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
- < GET_MODE_SIZE (SImode))
- target = SUBREG_REG (target);
- }
- else
- subtarget = target;
-
- if (GET_CODE (operands[3]) == CONST_INT)
- {
- /* Since we are inserting a known constant, we may be able to
- reduce the number of bits that we have to clear so that
- the mask becomes simple. */
- /* ??? This code does not check to see if the new mask is actually
- simpler. It may not be. */
- rtx op1 = gen_reg_rtx (SImode);
- /* ??? Truncate operand3 to fit in the bitfield. See comment before
- start of this pattern. */
- HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
- HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
-
- emit_insn (gen_andsi3 (op1, operands[0],
- gen_int_mode (~mask2, SImode)));
- emit_insn (gen_iorsi3 (subtarget, op1,
- gen_int_mode (op3_value << start_bit, SImode)));
- }
- else if (start_bit == 0
- && !(const_ok_for_arm (mask)
- || const_ok_for_arm (~mask)))
- {
- /* A Trick, since we are setting the bottom bits in the word,
- we can shift operand[3] up, operand[0] down, OR them together
- and rotate the result back again. This takes 3 insns, and
- the third might be mergeable into another op. */
- /* The shift up copes with the possibility that operand[3] is
- wider than the bitfield. */
- rtx op0 = gen_reg_rtx (SImode);
- rtx op1 = gen_reg_rtx (SImode);
-
- emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
- emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
- emit_insn (gen_iorsi3 (op1, op1, op0));
- emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
- }
- else if ((width + start_bit == 32)
- && !(const_ok_for_arm (mask)
- || const_ok_for_arm (~mask)))
- {
- /* Similar trick, but slightly less efficient. */
-
- rtx op0 = gen_reg_rtx (SImode);
- rtx op1 = gen_reg_rtx (SImode);
-
- emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
- emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
- emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
- emit_insn (gen_iorsi3 (subtarget, op1, op0));
- }
- else
- {
- rtx op0 = gen_int_mode (mask, SImode);
- rtx op1 = gen_reg_rtx (SImode);
- rtx op2 = gen_reg_rtx (SImode);
-
- if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
- {
- rtx tmp = gen_reg_rtx (SImode);
-
- emit_insn (gen_movsi (tmp, op0));
- op0 = tmp;
- }
-
- /* Mask out any bits in operand[3] that are not needed. */
- emit_insn (gen_andsi3 (op1, operands[3], op0));
-
- if (GET_CODE (op0) == CONST_INT
- && (const_ok_for_arm (mask << start_bit)
- || const_ok_for_arm (~(mask << start_bit))))
- {
- op0 = gen_int_mode (~(mask << start_bit), SImode);
- emit_insn (gen_andsi3 (op2, operands[0], op0));
- }
- else
- {
- if (GET_CODE (op0) == CONST_INT)
- {
- rtx tmp = gen_reg_rtx (SImode);
-
- emit_insn (gen_movsi (tmp, op0));
- op0 = tmp;
- }
-
- if (start_bit != 0)
- emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
-
- emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
- }
-
- if (start_bit != 0)
- emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
-
- emit_insn (gen_iorsi3 (subtarget, op1, op2));
- }
-
- if (subtarget != target)
- {
- /* If TARGET is still a SUBREG, then it must be wider than a word,
- so we must be careful only to set the subword we were asked to. */
- if (GET_CODE (target) == SUBREG)
- emit_move_insn (target, subtarget);
- else
- emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
- }
-
- DONE;
- }"
-)
-
-; constants for op 2 will never be given to these patterns.
-(define_insn_and_split "*anddi_notdi_di"
- [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
- (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
- (match_operand:DI 2 "s_register_operand" "0,r")))]
- "TARGET_ARM"
- "#"
- "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
- [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
- (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
- "
- {
- operands[3] = gen_highpart (SImode, operands[0]);
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[4] = gen_highpart (SImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- operands[5] = gen_highpart (SImode, operands[2]);
- operands[2] = gen_lowpart (SImode, operands[2]);
- }"
- [(set_attr "length" "8")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn_and_split "*anddi_notzesidi_di"
- [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
- (and:DI (not:DI (zero_extend:DI
- (match_operand:SI 2 "s_register_operand" "r,r")))
- (match_operand:DI 1 "s_register_operand" "0,?r")))]
- "TARGET_ARM"
- "@
- bic%?\\t%Q0, %Q1, %2
- #"
- ; (not (zero_extend ...)) allows us to just copy the high word from
- ; operand1 to operand0.
- "TARGET_ARM
- && reload_completed
- && operands[0] != operands[1]"
- [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
- (set (match_dup 3) (match_dup 4))]
- "
- {
- operands[3] = gen_highpart (SImode, operands[0]);
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[4] = gen_highpart (SImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- }"
- [(set_attr "length" "4,8")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn_and_split "*anddi_notsesidi_di"
- [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
- (and:DI (not:DI (sign_extend:DI
- (match_operand:SI 2 "s_register_operand" "r,r")))
- (match_operand:DI 1 "s_register_operand" "0,r")))]
- "TARGET_ARM"
- "#"
- "TARGET_ARM && reload_completed"
- [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
- (set (match_dup 3) (and:SI (not:SI
- (ashiftrt:SI (match_dup 2) (const_int 31)))
- (match_dup 4)))]
- "
- {
- operands[3] = gen_highpart (SImode, operands[0]);
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[4] = gen_highpart (SImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- }"
- [(set_attr "length" "8")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "andsi_notsi_si"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
- (match_operand:SI 1 "s_register_operand" "r")))]
- "TARGET_ARM"
- "bic%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")]
-)
-
-(define_insn "bicsi3"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
- (match_operand:SI 2 "register_operand" "0")))]
- "TARGET_THUMB"
- "bic\\t%0, %0, %1"
- [(set_attr "length" "2")]
-)
-
-(define_insn "andsi_not_shiftsi_si"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (and:SI (not:SI (match_operator:SI 4 "shift_operator"
- [(match_operand:SI 2 "s_register_operand" "r")
- (match_operand:SI 3 "arm_rhs_operand" "rM")]))
- (match_operand:SI 1 "s_register_operand" "r")))]
- "TARGET_ARM"
- "bic%?\\t%0, %1, %2%S4"
- [(set_attr "predicable" "yes")
- (set_attr "shift" "2")
- (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
- (const_string "alu_shift")
- (const_string "alu_shift_reg")))]
-)
-
-(define_insn "*andsi_notsi_si_compare0"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV
- (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
- (match_operand:SI 1 "s_register_operand" "r"))
- (const_int 0)))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
- "TARGET_ARM"
- "bic%?s\\t%0, %1, %2"
- [(set_attr "conds" "set")]
-)
-
-(define_insn "*andsi_notsi_si_compare0_scratch"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV
- (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
- (match_operand:SI 1 "s_register_operand" "r"))
- (const_int 0)))
- (clobber (match_scratch:SI 0 "=r"))]
- "TARGET_ARM"
- "bic%?s\\t%0, %1, %2"
- [(set_attr "conds" "set")]
-)
-
-(define_insn "iordi3"
- [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
- (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
- (match_operand:DI 2 "s_register_operand" "r,r")))]
- "TARGET_ARM && ! TARGET_IWMMXT"
- "#"
- [(set_attr "length" "8")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*iordi_zesidi_di"
- [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
- (ior:DI (zero_extend:DI
- (match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:DI 1 "s_register_operand" "0,?r")))]
- "TARGET_ARM"
- "@
- orr%?\\t%Q0, %Q1, %2
- #"
- [(set_attr "length" "4,8")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*iordi_sesidi_di"
- [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
- (ior:DI (sign_extend:DI
- (match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:DI 1 "s_register_operand" "?r,0")))]
- "TARGET_ARM"
- "#"
- [(set_attr "length" "8")
- (set_attr "predicable" "yes")]
-)
-
-(define_expand "iorsi3"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (ior:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "reg_or_int_operand" "")))]
- "TARGET_EITHER"
- "
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- if (TARGET_ARM)
- {
- arm_split_constant (IOR, SImode, NULL_RTX,
- INTVAL (operands[2]), operands[0], operands[1],
- optimize && !no_new_pseudos);
- DONE;
- }
- else /* TARGET_THUMB */
- operands [2] = force_reg (SImode, operands [2]);
- }
- "
-)
-
-(define_insn_and_split "*arm_iorsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
- (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
- "TARGET_ARM"
- "@
- orr%?\\t%0, %1, %2
- #"
- "TARGET_ARM
- && GET_CODE (operands[2]) == CONST_INT
- && !const_ok_for_arm (INTVAL (operands[2]))"
- [(clobber (const_int 0))]
- "
- arm_split_constant (IOR, SImode, curr_insn,
- INTVAL (operands[2]), operands[0], operands[1], 0);
- DONE;
- "
- [(set_attr "length" "4,16")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*thumb_iorsi3"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (ior:SI (match_operand:SI 1 "register_operand" "%0")
- (match_operand:SI 2 "register_operand" "l")))]
- "TARGET_THUMB"
- "orr\\t%0, %0, %2"
- [(set_attr "length" "2")]
-)
-
-(define_peephole2
- [(match_scratch:SI 3 "r")
- (set (match_operand:SI 0 "arm_general_register_operand" "")
- (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
- (match_operand:SI 2 "const_int_operand" "")))]
- "TARGET_ARM
- && !const_ok_for_arm (INTVAL (operands[2]))
- && const_ok_for_arm (~INTVAL (operands[2]))"
- [(set (match_dup 3) (match_dup 2))
- (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
- ""
-)
-
-(define_insn "*iorsi3_compare0"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
- (match_operand:SI 2 "arm_rhs_operand" "rI"))
- (const_int 0)))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (ior:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM"
- "orr%?s\\t%0, %1, %2"
- [(set_attr "conds" "set")]
-)
-
-(define_insn "*iorsi3_compare0_scratch"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
- (match_operand:SI 2 "arm_rhs_operand" "rI"))
- (const_int 0)))
- (clobber (match_scratch:SI 0 "=r"))]
- "TARGET_ARM"
- "orr%?s\\t%0, %1, %2"
- [(set_attr "conds" "set")]
-)
-
-(define_insn "xordi3"
- [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
- (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
- (match_operand:DI 2 "s_register_operand" "r,r")))]
- "TARGET_ARM && !TARGET_IWMMXT"
- "#"
- [(set_attr "length" "8")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*xordi_zesidi_di"
- [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
- (xor:DI (zero_extend:DI
- (match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:DI 1 "s_register_operand" "0,?r")))]
- "TARGET_ARM"
- "@
- eor%?\\t%Q0, %Q1, %2
- #"
- [(set_attr "length" "4,8")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*xordi_sesidi_di"
- [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
- (xor:DI (sign_extend:DI
- (match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:DI 1 "s_register_operand" "?r,0")))]
- "TARGET_ARM"
- "#"
- [(set_attr "length" "8")
- (set_attr "predicable" "yes")]
-)
-
-(define_expand "xorsi3"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (xor:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "arm_rhs_operand" "")))]
- "TARGET_EITHER"
- "if (TARGET_THUMB)
- if (GET_CODE (operands[2]) == CONST_INT)
- operands[2] = force_reg (SImode, operands[2]);
- "
-)
-
-(define_insn "*arm_xorsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (xor:SI (match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "arm_rhs_operand" "rI")))]
- "TARGET_ARM"
- "eor%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")]
-)
-
-(define_insn "*thumb_xorsi3"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (xor:SI (match_operand:SI 1 "register_operand" "%0")
- (match_operand:SI 2 "register_operand" "l")))]
- "TARGET_THUMB"
- "eor\\t%0, %0, %2"
- [(set_attr "length" "2")]
-)
-
-(define_insn "*xorsi3_compare0"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "arm_rhs_operand" "rI"))
- (const_int 0)))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (xor:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM"
- "eor%?s\\t%0, %1, %2"
- [(set_attr "conds" "set")]
-)
-
-(define_insn "*xorsi3_compare0_scratch"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
- (match_operand:SI 1 "arm_rhs_operand" "rI"))
- (const_int 0)))]
- "TARGET_ARM"
- "teq%?\\t%0, %1"
- [(set_attr "conds" "set")]
-)
-
-; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
-; (NOT D) we can sometimes merge the final NOT into one of the following
-; insns.
-
-(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
- (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
- (match_operand:SI 3 "arm_rhs_operand" "")))
- (clobber (match_operand:SI 4 "s_register_operand" ""))]
- "TARGET_ARM"
- [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
- (not:SI (match_dup 3))))
- (set (match_dup 0) (not:SI (match_dup 4)))]
- ""
-)
-
-(define_insn "*andsi_iorsi3_notsi"
- [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
- (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
- (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
- (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
- "TARGET_ARM"
- "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
- [(set_attr "length" "8")
- (set_attr "predicable" "yes")]
-)
-
-(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (match_operator:SI 1 "logical_binary_operator"
- [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
- (match_operand:SI 3 "const_int_operand" "")
- (match_operand:SI 4 "const_int_operand" ""))
- (match_operator:SI 9 "logical_binary_operator"
- [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
- (match_operand:SI 6 "const_int_operand" ""))
- (match_operand:SI 7 "s_register_operand" "")])]))
- (clobber (match_operand:SI 8 "s_register_operand" ""))]
- "TARGET_ARM
- && GET_CODE (operands[1]) == GET_CODE (operands[9])
- && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
- [(set (match_dup 8)
- (match_op_dup 1
- [(ashift:SI (match_dup 2) (match_dup 4))
- (match_dup 5)]))
- (set (match_dup 0)
- (match_op_dup 1
- [(lshiftrt:SI (match_dup 8) (match_dup 6))
- (match_dup 7)]))]
- "
- operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
-")
-
-(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (match_operator:SI 1 "logical_binary_operator"
- [(match_operator:SI 9 "logical_binary_operator"
- [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
- (match_operand:SI 6 "const_int_operand" ""))
- (match_operand:SI 7 "s_register_operand" "")])
- (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
- (match_operand:SI 3 "const_int_operand" "")
- (match_operand:SI 4 "const_int_operand" ""))]))
- (clobber (match_operand:SI 8 "s_register_operand" ""))]
- "TARGET_ARM
- && GET_CODE (operands[1]) == GET_CODE (operands[9])
- && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
- [(set (match_dup 8)
- (match_op_dup 1
- [(ashift:SI (match_dup 2) (match_dup 4))
- (match_dup 5)]))
- (set (match_dup 0)
- (match_op_dup 1
- [(lshiftrt:SI (match_dup 8) (match_dup 6))
- (match_dup 7)]))]
- "
- operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
-")
-
-(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (match_operator:SI 1 "logical_binary_operator"
- [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
- (match_operand:SI 3 "const_int_operand" "")
- (match_operand:SI 4 "const_int_operand" ""))
- (match_operator:SI 9 "logical_binary_operator"
- [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
- (match_operand:SI 6 "const_int_operand" ""))
- (match_operand:SI 7 "s_register_operand" "")])]))
- (clobber (match_operand:SI 8 "s_register_operand" ""))]
- "TARGET_ARM
- && GET_CODE (operands[1]) == GET_CODE (operands[9])
- && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
- [(set (match_dup 8)
- (match_op_dup 1
- [(ashift:SI (match_dup 2) (match_dup 4))
- (match_dup 5)]))
- (set (match_dup 0)
- (match_op_dup 1
- [(ashiftrt:SI (match_dup 8) (match_dup 6))
- (match_dup 7)]))]
- "
- operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
-")
-
-(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (match_operator:SI 1 "logical_binary_operator"
- [(match_operator:SI 9 "logical_binary_operator"
- [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
- (match_operand:SI 6 "const_int_operand" ""))
- (match_operand:SI 7 "s_register_operand" "")])
- (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
- (match_operand:SI 3 "const_int_operand" "")
- (match_operand:SI 4 "const_int_operand" ""))]))
- (clobber (match_operand:SI 8 "s_register_operand" ""))]
- "TARGET_ARM
- && GET_CODE (operands[1]) == GET_CODE (operands[9])
- && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
- [(set (match_dup 8)
- (match_op_dup 1
- [(ashift:SI (match_dup 2) (match_dup 4))
- (match_dup 5)]))
- (set (match_dup 0)
- (match_op_dup 1
- [(ashiftrt:SI (match_dup 8) (match_dup 6))
- (match_dup 7)]))]
- "
- operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
-")
-
-
-;; Minimum and maximum insns
-
-(define_expand "smaxsi3"
- [(parallel [
- (set (match_operand:SI 0 "s_register_operand" "")
- (smax:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "arm_rhs_operand" "")))
- (clobber (reg:CC CC_REGNUM))])]
- "TARGET_ARM"
- "
- if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
- {
- /* No need for a clobber of the condition code register here. */
- emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_SMAX (SImode, operands[1],
- operands[2])));
- DONE;
- }
-")
-
-(define_insn "*smax_0"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (smax:SI (match_operand:SI 1 "s_register_operand" "r")
- (const_int 0)))]
- "TARGET_ARM"
- "bic%?\\t%0, %1, %1, asr #31"
- [(set_attr "predicable" "yes")]
-)
-
-(define_insn "*smax_m1"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (smax:SI (match_operand:SI 1 "s_register_operand" "r")
- (const_int -1)))]
- "TARGET_ARM"
- "orr%?\\t%0, %1, %1, asr #31"
- [(set_attr "predicable" "yes")]
-)
-
-(define_insn "*smax_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
- (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "@
- cmp\\t%1, %2\;movlt\\t%0, %2
- cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
- [(set_attr "conds" "clob")
- (set_attr "length" "8,12")]
-)
-
-(define_expand "sminsi3"
- [(parallel [
- (set (match_operand:SI 0 "s_register_operand" "")
- (smin:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "arm_rhs_operand" "")))
- (clobber (reg:CC CC_REGNUM))])]
- "TARGET_ARM"
- "
- if (operands[2] == const0_rtx)
- {
- /* No need for a clobber of the condition code register here. */
- emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_SMIN (SImode, operands[1],
- operands[2])));
- DONE;
- }
-")
-
-(define_insn "*smin_0"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (smin:SI (match_operand:SI 1 "s_register_operand" "r")
- (const_int 0)))]
- "TARGET_ARM"
- "and%?\\t%0, %1, %1, asr #31"
- [(set_attr "predicable" "yes")]
-)
-
-(define_insn "*smin_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
- (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "@
- cmp\\t%1, %2\;movge\\t%0, %2
- cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
- [(set_attr "conds" "clob")
- (set_attr "length" "8,12")]
-)
-
-(define_insn "umaxsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
- (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
- (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "@
- cmp\\t%1, %2\;movcc\\t%0, %2
- cmp\\t%1, %2\;movcs\\t%0, %1
- cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
- [(set_attr "conds" "clob")
- (set_attr "length" "8,8,12")]
-)
-
-(define_insn "uminsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
- (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
- (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "@
- cmp\\t%1, %2\;movcs\\t%0, %2
- cmp\\t%1, %2\;movcc\\t%0, %1
- cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
- [(set_attr "conds" "clob")
- (set_attr "length" "8,8,12")]
-)
-
-(define_insn "*store_minmaxsi"
- [(set (match_operand:SI 0 "memory_operand" "=m")
- (match_operator:SI 3 "minmax_operator"
- [(match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "s_register_operand" "r")]))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "*
- operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
- operands[1], operands[2]);
- output_asm_insn (\"cmp\\t%1, %2\", operands);
- output_asm_insn (\"str%d3\\t%1, %0\", operands);
- output_asm_insn (\"str%D3\\t%2, %0\", operands);
- return \"\";
- "
- [(set_attr "conds" "clob")
- (set_attr "length" "12")
- (set_attr "type" "store1")]
-)
-
-; Reject the frame pointer in operand[1], since reloading this after
-; it has been eliminated can cause carnage.
-(define_insn "*minmax_arithsi"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (match_operator:SI 4 "shiftable_operator"
- [(match_operator:SI 5 "minmax_operator"
- [(match_operand:SI 2 "s_register_operand" "r,r")
- (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
- (match_operand:SI 1 "s_register_operand" "0,?r")]))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM && !arm_eliminable_register (operands[1])"
- "*
- {
- enum rtx_code code = GET_CODE (operands[4]);
-
- operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
- operands[2], operands[3]);
- output_asm_insn (\"cmp\\t%2, %3\", operands);
- output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
- if (which_alternative != 0 || operands[3] != const0_rtx
- || (code != PLUS && code != MINUS && code != IOR && code != XOR))
- output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
- return \"\";
- }"
- [(set_attr "conds" "clob")
- (set_attr "length" "12")]
-)
-
-
-;; Shift and rotation insns
-
-(define_expand "ashldi3"
- [(set (match_operand:DI 0 "s_register_operand" "")
- (ashift:DI (match_operand:DI 1 "s_register_operand" "")
- (match_operand:SI 2 "reg_or_int_operand" "")))]
- "TARGET_ARM"
- "
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
- {
- emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
- DONE;
- }
- /* Ideally we shouldn't fail here if we could know that operands[1]
- ends up already living in an iwmmxt register. Otherwise it's
- cheaper to have the alternate code being generated than moving
- values to iwmmxt regs and back. */
- FAIL;
- }
- else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
- FAIL;
- "
-)
-
-(define_insn "arm_ashldi3_1bit"
- [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
- (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
- (const_int 1)))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
- [(set_attr "conds" "clob")
- (set_attr "length" "8")]
-)
-
-(define_expand "ashlsi3"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (ashift:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "arm_rhs_operand" "")))]
- "TARGET_EITHER"
- "
- if (GET_CODE (operands[2]) == CONST_INT
- && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
- {
- emit_insn (gen_movsi (operands[0], const0_rtx));
- DONE;
- }
- "
-)
-
-(define_insn "*thumb_ashlsi3"
- [(set (match_operand:SI 0 "register_operand" "=l,l")
- (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
- (match_operand:SI 2 "nonmemory_operand" "N,l")))]
- "TARGET_THUMB"
- "lsl\\t%0, %1, %2"
- [(set_attr "length" "2")]
-)
-
-(define_expand "ashrdi3"
- [(set (match_operand:DI 0 "s_register_operand" "")
- (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
- (match_operand:SI 2 "reg_or_int_operand" "")))]
- "TARGET_ARM"
- "
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
- {
- emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
- DONE;
- }
- /* Ideally we shouldn't fail here if we could know that operands[1]
- ends up already living in an iwmmxt register. Otherwise it's
- cheaper to have the alternate code being generated than moving
- values to iwmmxt regs and back. */
- FAIL;
- }
- else if (!TARGET_REALLY_IWMMXT)
- FAIL;
- "
-)
-
-(define_insn "arm_ashrdi3_1bit"
- [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
- (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
- (const_int 1)))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
- [(set_attr "conds" "clob")
- (set_attr "length" "8")]
-)
-
-(define_expand "ashrsi3"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "arm_rhs_operand" "")))]
- "TARGET_EITHER"
- "
- if (GET_CODE (operands[2]) == CONST_INT
- && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
- operands[2] = GEN_INT (31);
- "
-)
-
-(define_insn "*thumb_ashrsi3"
- [(set (match_operand:SI 0 "register_operand" "=l,l")
- (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
- (match_operand:SI 2 "nonmemory_operand" "N,l")))]
- "TARGET_THUMB"
- "asr\\t%0, %1, %2"
- [(set_attr "length" "2")]
-)
-
-(define_expand "lshrdi3"
- [(set (match_operand:DI 0 "s_register_operand" "")
- (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
- (match_operand:SI 2 "reg_or_int_operand" "")))]
- "TARGET_ARM"
- "
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
- {
- emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
- DONE;
- }
- /* Ideally we shouldn't fail here if we could know that operands[1]
- ends up already living in an iwmmxt register. Otherwise it's
- cheaper to have the alternate code being generated than moving
- values to iwmmxt regs and back. */
- FAIL;
- }
- else if (!TARGET_REALLY_IWMMXT)
- FAIL;
- "
-)
-
-(define_insn "arm_lshrdi3_1bit"
- [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
- (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
- (const_int 1)))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
- [(set_attr "conds" "clob")
- (set_attr "length" "8")]
-)
-
-(define_expand "lshrsi3"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "arm_rhs_operand" "")))]
- "TARGET_EITHER"
- "
- if (GET_CODE (operands[2]) == CONST_INT
- && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
- {
- emit_insn (gen_movsi (operands[0], const0_rtx));
- DONE;
- }
- "
-)
-
-(define_insn "*thumb_lshrsi3"
- [(set (match_operand:SI 0 "register_operand" "=l,l")
- (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
- (match_operand:SI 2 "nonmemory_operand" "N,l")))]
- "TARGET_THUMB"
- "lsr\\t%0, %1, %2"
- [(set_attr "length" "2")]
-)
-
-(define_expand "rotlsi3"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "reg_or_int_operand" "")))]
- "TARGET_ARM"
- "
- if (GET_CODE (operands[2]) == CONST_INT)
- operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
- else
- {
- rtx reg = gen_reg_rtx (SImode);
- emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
- operands[2] = reg;
- }
- "
-)
-
-(define_expand "rotrsi3"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "arm_rhs_operand" "")))]
- "TARGET_EITHER"
- "
- if (TARGET_ARM)
- {
- if (GET_CODE (operands[2]) == CONST_INT
- && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
- operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
- }
- else /* TARGET_THUMB */
- {
- if (GET_CODE (operands [2]) == CONST_INT)
- operands [2] = force_reg (SImode, operands[2]);
- }
- "
-)
-
-(define_insn "*thumb_rotrsi3"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (rotatert:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "register_operand" "l")))]
- "TARGET_THUMB"
- "ror\\t%0, %0, %2"
- [(set_attr "length" "2")]
-)
-
-(define_insn "*arm_shiftsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (match_operator:SI 3 "shift_operator"
- [(match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
- "TARGET_ARM"
- "mov%?\\t%0, %1%S3"
- [(set_attr "predicable" "yes")
- (set_attr "shift" "1")
- (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
- (const_string "alu_shift")
- (const_string "alu_shift_reg")))]
-)
-
-(define_insn "*shiftsi3_compare0"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
- [(match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "arm_rhs_operand" "rM")])
- (const_int 0)))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
- "TARGET_ARM"
- "mov%?s\\t%0, %1%S3"
- [(set_attr "conds" "set")
- (set_attr "shift" "1")
- (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
- (const_string "alu_shift")
- (const_string "alu_shift_reg")))]
-)
-
-(define_insn "*shiftsi3_compare0_scratch"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
- [(match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "arm_rhs_operand" "rM")])
- (const_int 0)))
- (clobber (match_scratch:SI 0 "=r"))]
- "TARGET_ARM"
- "mov%?s\\t%0, %1%S3"
- [(set_attr "conds" "set")
- (set_attr "shift" "1")]
-)
-
-(define_insn "*notsi_shiftsi"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (not:SI (match_operator:SI 3 "shift_operator"
- [(match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
- "TARGET_ARM"
- "mvn%?\\t%0, %1%S3"
- [(set_attr "predicable" "yes")
- (set_attr "shift" "1")
- (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
- (const_string "alu_shift")
- (const_string "alu_shift_reg")))]
-)
-
-(define_insn "*notsi_shiftsi_compare0"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
- [(match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "arm_rhs_operand" "rM")]))
- (const_int 0)))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
- "TARGET_ARM"
- "mvn%?s\\t%0, %1%S3"
- [(set_attr "conds" "set")
- (set_attr "shift" "1")
- (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
- (const_string "alu_shift")
- (const_string "alu_shift_reg")))]
-)
-
-(define_insn "*not_shiftsi_compare0_scratch"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
- [(match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "arm_rhs_operand" "rM")]))
- (const_int 0)))
- (clobber (match_scratch:SI 0 "=r"))]
- "TARGET_ARM"
- "mvn%?s\\t%0, %1%S3"
- [(set_attr "conds" "set")
- (set_attr "shift" "1")
- (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
- (const_string "alu_shift")
- (const_string "alu_shift_reg")))]
-)
-
-;; 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" "")))]
- "TARGET_THUMB"
- "
- {
- 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);
- }"
-)
-
-
-;; Unary arithmetic insns
-
-(define_expand "negdi2"
- [(parallel
- [(set (match_operand:DI 0 "s_register_operand" "")
- (neg:DI (match_operand:DI 1 "s_register_operand" "")))
- (clobber (reg:CC CC_REGNUM))])]
- "TARGET_EITHER"
- "
- if (TARGET_THUMB)
- {
- if (GET_CODE (operands[1]) != REG)
- operands[1] = force_reg (SImode, operands[1]);
- }
- "
-)
-
-;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
-;; The second alternative is to allow the common case of a *full* overlap.
-(define_insn "*arm_negdi2"
- [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
- (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
- [(set_attr "conds" "clob")
- (set_attr "length" "8")]
-)
-
-(define_insn "*thumb_negdi2"
- [(set (match_operand:DI 0 "register_operand" "=&l")
- (neg:DI (match_operand:DI 1 "register_operand" "l")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_THUMB"
- "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
- [(set_attr "length" "6")]
-)
-
-(define_expand "negsi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
- "TARGET_EITHER"
- ""
-)
-
-(define_insn "*arm_negsi2"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
- "TARGET_ARM"
- "rsb%?\\t%0, %1, #0"
- [(set_attr "predicable" "yes")]
-)
-
-(define_insn "*thumb_negsi2"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (neg:SI (match_operand:SI 1 "register_operand" "l")))]
- "TARGET_THUMB"
- "neg\\t%0, %1"
- [(set_attr "length" "2")]
-)
-
-(define_expand "negsf2"
- [(set (match_operand:SF 0 "s_register_operand" "")
- (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- ""
-)
-
-(define_expand "negdf2"
- [(set (match_operand:DF 0 "s_register_operand" "")
- (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "")
-
-;; abssi2 doesn't really clobber the condition codes if a different register
-;; is being set. To keep things simple, assume during rtl manipulations that
-;; it does, but tell the final scan operator the truth. Similarly for
-;; (neg (abs...))
-
-(define_expand "abssi2"
- [(parallel
- [(set (match_operand:SI 0 "s_register_operand" "")
- (abs:SI (match_operand:SI 1 "s_register_operand" "")))
- (clobber (reg:CC CC_REGNUM))])]
- "TARGET_ARM"
- "")
-
-(define_insn "*arm_abssi2"
- [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
- (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "@
- cmp\\t%0, #0\;rsblt\\t%0, %0, #0
- eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
- [(set_attr "conds" "clob,*")
- (set_attr "shift" "1")
- ;; predicable can't be set based on the variant, so left as no
- (set_attr "length" "8")]
-)
-
-(define_insn "*neg_abssi2"
- [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
- (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "@
- cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
- eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
- [(set_attr "conds" "clob,*")
- (set_attr "shift" "1")
- ;; predicable can't be set based on the variant, so left as no
- (set_attr "length" "8")]
-)
-
-(define_expand "abssf2"
- [(set (match_operand:SF 0 "s_register_operand" "")
- (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "")
-
-(define_expand "absdf2"
- [(set (match_operand:DF 0 "s_register_operand" "")
- (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "")
-
-(define_expand "sqrtsf2"
- [(set (match_operand:SF 0 "s_register_operand" "")
- (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "")
-
-(define_expand "sqrtdf2"
- [(set (match_operand:DF 0 "s_register_operand" "")
- (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "")
-
-(define_insn_and_split "one_cmpldi2"
- [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
- (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
- "TARGET_ARM"
- "#"
- "TARGET_ARM && reload_completed"
- [(set (match_dup 0) (not:SI (match_dup 1)))
- (set (match_dup 2) (not:SI (match_dup 3)))]
- "
- {
- operands[2] = gen_highpart (SImode, operands[0]);
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[3] = gen_highpart (SImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- }"
- [(set_attr "length" "8")
- (set_attr "predicable" "yes")]
-)
-
-(define_expand "one_cmplsi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (not:SI (match_operand:SI 1 "s_register_operand" "")))]
- "TARGET_EITHER"
- ""
-)
-
-(define_insn "*arm_one_cmplsi2"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
- "TARGET_ARM"
- "mvn%?\\t%0, %1"
- [(set_attr "predicable" "yes")]
-)
-
-(define_insn "*thumb_one_cmplsi2"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (not:SI (match_operand:SI 1 "register_operand" "l")))]
- "TARGET_THUMB"
- "mvn\\t%0, %1"
- [(set_attr "length" "2")]
-)
-
-(define_insn "*notsi_compare0"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
- (const_int 0)))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (not:SI (match_dup 1)))]
- "TARGET_ARM"
- "mvn%?s\\t%0, %1"
- [(set_attr "conds" "set")]
-)
-
-(define_insn "*notsi_compare0_scratch"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
- (const_int 0)))
- (clobber (match_scratch:SI 0 "=r"))]
- "TARGET_ARM"
- "mvn%?s\\t%0, %1"
- [(set_attr "conds" "set")]
-)
-
-;; Fixed <--> Floating conversion insns
-
-(define_expand "floatsisf2"
- [(set (match_operand:SF 0 "s_register_operand" "")
- (float:SF (match_operand:SI 1 "s_register_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "
- if (TARGET_MAVERICK)
- {
- emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
- DONE;
- }
-")
-
-(define_expand "floatsidf2"
- [(set (match_operand:DF 0 "s_register_operand" "")
- (float:DF (match_operand:SI 1 "s_register_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "
- if (TARGET_MAVERICK)
- {
- emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
- DONE;
- }
-")
-
-(define_expand "fix_truncsfsi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "
- if (TARGET_MAVERICK)
- {
- if (!cirrus_fp_register (operands[0], SImode))
- operands[0] = force_reg (SImode, operands[0]);
- if (!cirrus_fp_register (operands[1], SFmode))
- operands[1] = force_reg (SFmode, operands[0]);
- emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
- DONE;
- }
-")
-
-(define_expand "fix_truncdfsi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "
- if (TARGET_MAVERICK)
- {
- if (!cirrus_fp_register (operands[1], DFmode))
- operands[1] = force_reg (DFmode, operands[0]);
- emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
- DONE;
- }
-")
-
-;; Truncation insns
-
-(define_expand "truncdfsf2"
- [(set (match_operand:SF 0 "s_register_operand" "")
- (float_truncate:SF
- (match_operand:DF 1 "s_register_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- ""
-)
-
-;; Zero and sign extension instructions.
-
-(define_insn "zero_extendsidi2"
- [(set (match_operand:DI 0 "s_register_operand" "=r")
- (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
- "TARGET_ARM"
- "*
- if (REGNO (operands[1])
- != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
- output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
- return \"mov%?\\t%R0, #0\";
- "
- [(set_attr "length" "8")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "zero_extendqidi2"
- [(set (match_operand:DI 0 "s_register_operand" "=r,r")
- (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
- "TARGET_ARM"
- "@
- and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
- ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
- [(set_attr "length" "8")
- (set_attr "predicable" "yes")
- (set_attr "type" "*,load_byte")
- (set_attr "pool_range" "*,4092")
- (set_attr "neg_pool_range" "*,4084")]
-)
-
-(define_insn "extendsidi2"
- [(set (match_operand:DI 0 "s_register_operand" "=r")
- (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
- "TARGET_ARM"
- "*
- if (REGNO (operands[1])
- != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
- output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
- return \"mov%?\\t%R0, %Q0, asr #31\";
- "
- [(set_attr "length" "8")
- (set_attr "shift" "1")
- (set_attr "predicable" "yes")]
-)
-
-(define_expand "zero_extendhisi2"
- [(set (match_dup 2)
- (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
- (const_int 16)))
- (set (match_operand:SI 0 "s_register_operand" "")
- (lshiftrt:SI (match_dup 2) (const_int 16)))]
- "TARGET_EITHER"
- "
- {
- if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
- {
- emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_ZERO_EXTEND (SImode, operands[1])));
- DONE;
- }
-
- if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
- {
- emit_insn (gen_movhi_bytes (operands[0], operands[1]));
- DONE;
- }
-
- if (!s_register_operand (operands[1], HImode))
- operands[1] = copy_to_mode_reg (HImode, operands[1]);
-
- if (arm_arch6)
- {
- emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_ZERO_EXTEND (SImode, operands[1])));
- DONE;
- }
-
- operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = gen_reg_rtx (SImode);
- }"
-)
-
-(define_insn "*thumb_zero_extendhisi2"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
- "TARGET_THUMB && !arm_arch6"
- "*
- rtx mem = XEXP (operands[1], 0);
-
- if (GET_CODE (mem) == CONST)
- mem = XEXP (mem, 0);
-
- if (GET_CODE (mem) == LABEL_REF)
- return \"ldr\\t%0, %1\";
-
- if (GET_CODE (mem) == PLUS)
- {
- rtx a = XEXP (mem, 0);
- rtx b = XEXP (mem, 1);
-
- /* This can happen due to bugs in reload. */
- if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
- {
- rtx ops[2];
- ops[0] = operands[0];
- ops[1] = a;
-
- output_asm_insn (\"mov %0, %1\", ops);
-
- XEXP (mem, 0) = operands[0];
- }
-
- else if ( GET_CODE (a) == LABEL_REF
- && GET_CODE (b) == CONST_INT)
- return \"ldr\\t%0, %1\";
- }
-
- return \"ldrh\\t%0, %1\";
- "
- [(set_attr "length" "4")
- (set_attr "type" "load_byte")
- (set_attr "pool_range" "60")]
-)
-
-(define_insn "*thumb_zero_extendhisi2_v6"
- [(set (match_operand:SI 0 "register_operand" "=l,l")
- (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
- "TARGET_THUMB && arm_arch6"
- "*
- rtx mem;
-
- if (which_alternative == 0)
- return \"uxth\\t%0, %1\";
-
- mem = XEXP (operands[1], 0);
-
- if (GET_CODE (mem) == CONST)
- mem = XEXP (mem, 0);
-
- if (GET_CODE (mem) == LABEL_REF)
- return \"ldr\\t%0, %1\";
-
- if (GET_CODE (mem) == PLUS)
- {
- rtx a = XEXP (mem, 0);
- rtx b = XEXP (mem, 1);
-
- /* This can happen due to bugs in reload. */
- if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
- {
- rtx ops[2];
- ops[0] = operands[0];
- ops[1] = a;
-
- output_asm_insn (\"mov %0, %1\", ops);
-
- XEXP (mem, 0) = operands[0];
- }
-
- else if ( GET_CODE (a) == LABEL_REF
- && GET_CODE (b) == CONST_INT)
- return \"ldr\\t%0, %1\";
- }
-
- return \"ldrh\\t%0, %1\";
- "
- [(set_attr "length" "2,4")
- (set_attr "type" "alu_shift,load_byte")
- (set_attr "pool_range" "*,60")]
-)
-
-(define_insn "*arm_zero_extendhisi2"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
- "TARGET_ARM && arm_arch4 && !arm_arch6"
- "ldr%?h\\t%0, %1"
- [(set_attr "type" "load_byte")
- (set_attr "predicable" "yes")
- (set_attr "pool_range" "256")
- (set_attr "neg_pool_range" "244")]
-)
-
-(define_insn "*arm_zero_extendhisi2_v6"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
- "TARGET_ARM && arm_arch6"
- "@
- uxth%?\\t%0, %1
- ldr%?h\\t%0, %1"
- [(set_attr "type" "alu_shift,load_byte")
- (set_attr "predicable" "yes")
- (set_attr "pool_range" "*,256")
- (set_attr "neg_pool_range" "*,244")]
-)
-
-(define_insn "*arm_zero_extendhisi2addsi"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
- (match_operand:SI 2 "s_register_operand" "r")))]
- "TARGET_ARM && arm_arch6"
- "uxtah%?\\t%0, %2, %1"
- [(set_attr "type" "alu_shift")
- (set_attr "predicable" "yes")]
-)
-
-(define_expand "zero_extendqisi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
- "TARGET_EITHER"
- "
- if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
- {
- if (TARGET_ARM)
- {
- emit_insn (gen_andsi3 (operands[0],
- gen_lowpart (SImode, operands[1]),
- GEN_INT (255)));
- }
- else /* TARGET_THUMB */
- {
- rtx temp = gen_reg_rtx (SImode);
- rtx ops[3];
-
- operands[1] = copy_to_mode_reg (QImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
-
- ops[0] = temp;
- ops[1] = operands[1];
- ops[2] = GEN_INT (24);
-
- emit_insn (gen_rtx_SET (VOIDmode, ops[0],
- gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
-
- ops[0] = operands[0];
- ops[1] = temp;
- ops[2] = GEN_INT (24);
-
- emit_insn (gen_rtx_SET (VOIDmode, ops[0],
- gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
- }
- DONE;
- }
- "
-)
-
-(define_insn "*thumb_zero_extendqisi2"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
- "TARGET_THUMB && !arm_arch6"
- "ldrb\\t%0, %1"
- [(set_attr "length" "2")
- (set_attr "type" "load_byte")
- (set_attr "pool_range" "32")]
-)
-
-(define_insn "*thumb_zero_extendqisi2_v6"
- [(set (match_operand:SI 0 "register_operand" "=l,l")
- (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
- "TARGET_THUMB && arm_arch6"
- "@
- uxtb\\t%0, %1
- ldrb\\t%0, %1"
- [(set_attr "length" "2,2")
- (set_attr "type" "alu_shift,load_byte")
- (set_attr "pool_range" "*,32")]
-)
-
-(define_insn "*arm_zero_extendqisi2"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
- "TARGET_ARM && !arm_arch6"
- "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
- [(set_attr "type" "load_byte")
- (set_attr "predicable" "yes")
- (set_attr "pool_range" "4096")
- (set_attr "neg_pool_range" "4084")]
-)
-
-(define_insn "*arm_zero_extendqisi2_v6"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
- "TARGET_ARM && arm_arch6"
- "@
- uxtb%?\\t%0, %1
- ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
- [(set_attr "type" "alu_shift,load_byte")
- (set_attr "predicable" "yes")
- (set_attr "pool_range" "*,4096")
- (set_attr "neg_pool_range" "*,4084")]
-)
-
-(define_insn "*arm_zero_extendqisi2addsi"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
- (match_operand:SI 2 "s_register_operand" "r")))]
- "TARGET_ARM && arm_arch6"
- "uxtab%?\\t%0, %2, %1"
- [(set_attr "predicable" "yes")
- (set_attr "type" "alu_shift")]
-)
-
-(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
- (clobber (match_operand:SI 2 "s_register_operand" ""))]
- "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
- [(set (match_dup 2) (match_dup 1))
- (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
- ""
-)
-
-(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
- (clobber (match_operand:SI 2 "s_register_operand" ""))]
- "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
- [(set (match_dup 2) (match_dup 1))
- (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
- ""
-)
-
-(define_insn "*compareqi_eq0"
- [(set (reg:CC_Z CC_REGNUM)
- (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
- (const_int 0)))]
- "TARGET_ARM"
- "tst\\t%0, #255"
- [(set_attr "conds" "set")]
-)
-
-(define_expand "extendhisi2"
- [(set (match_dup 2)
- (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
- (const_int 16)))
- (set (match_operand:SI 0 "s_register_operand" "")
- (ashiftrt:SI (match_dup 2)
- (const_int 16)))]
- "TARGET_EITHER"
- "
- {
- if (GET_CODE (operands[1]) == MEM)
- {
- if (TARGET_THUMB)
- {
- emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
- DONE;
- }
- else if (arm_arch4)
- {
- emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_SIGN_EXTEND (SImode, operands[1])));
- DONE;
- }
- }
-
- if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
- {
- emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
- DONE;
- }
-
- if (!s_register_operand (operands[1], HImode))
- operands[1] = copy_to_mode_reg (HImode, operands[1]);
-
- if (arm_arch6)
- {
- if (TARGET_THUMB)
- emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
- else
- emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_SIGN_EXTEND (SImode, operands[1])));
-
- DONE;
- }
-
- operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = gen_reg_rtx (SImode);
- }"
-)
-
-(define_insn "thumb_extendhisi2"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
- (clobber (match_scratch:SI 2 "=&l"))]
- "TARGET_THUMB && !arm_arch6"
- "*
- {
- rtx ops[4];
- rtx mem = XEXP (operands[1], 0);
-
- /* 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 (mem) == CONST)
- mem = XEXP (mem, 0);
-
- if (GET_CODE (mem) == LABEL_REF)
- return \"ldr\\t%0, %1\";
-
- if (GET_CODE (mem) == PLUS)
- {
- rtx a = XEXP (mem, 0);
- rtx b = XEXP (mem, 1);
-
- if (GET_CODE (a) == LABEL_REF
- && GET_CODE (b) == CONST_INT)
- return \"ldr\\t%0, %1\";
-
- if (GET_CODE (b) == REG)
- return \"ldrsh\\t%0, %1\";
-
- ops[1] = a;
- ops[2] = b;
- }
- else
- {
- ops[1] = mem;
- ops[2] = const0_rtx;
- }
-
- gcc_assert (GET_CODE (ops[1]) == REG);
-
- 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")
- (set_attr "type" "load_byte")
- (set_attr "pool_range" "1020")]
-)
-
-;; We used to have an early-clobber on the scratch register here.
-;; However, there's a bug somewhere in reload which means that this
-;; can be partially ignored during spill allocation if the memory
-;; address also needs reloading; this causes us to die later on when
-;; we try to verify the operands. Fortunately, we don't really need
-;; the early-clobber: we can always use operand 0 if operand 2
-;; overlaps the address.
-(define_insn "*thumb_extendhisi2_insn_v6"
- [(set (match_operand:SI 0 "register_operand" "=l,l")
- (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
- (clobber (match_scratch:SI 2 "=X,l"))]
- "TARGET_THUMB && arm_arch6"
- "*
- {
- rtx ops[4];
- rtx mem;
-
- if (which_alternative == 0)
- return \"sxth\\t%0, %1\";
-
- mem = XEXP (operands[1], 0);
-
- /* 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 (mem) == CONST)
- mem = XEXP (mem, 0);
-
- if (GET_CODE (mem) == LABEL_REF)
- return \"ldr\\t%0, %1\";
-
- if (GET_CODE (mem) == PLUS)
- {
- rtx a = XEXP (mem, 0);
- rtx b = XEXP (mem, 1);
-
- if (GET_CODE (a) == LABEL_REF
- && GET_CODE (b) == CONST_INT)
- return \"ldr\\t%0, %1\";
-
- if (GET_CODE (b) == REG)
- return \"ldrsh\\t%0, %1\";
-
- ops[1] = a;
- ops[2] = b;
- }
- else
- {
- ops[1] = mem;
- ops[2] = const0_rtx;
- }
-
- gcc_assert (GET_CODE (ops[1]) == REG);
-
- ops[0] = operands[0];
- if (reg_mentioned_p (operands[2], ops[1]))
- ops[3] = ops[0];
- else
- ops[3] = operands[2];
- output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
- return \"\";
- }"
- [(set_attr "length" "2,4")
- (set_attr "type" "alu_shift,load_byte")
- (set_attr "pool_range" "*,1020")]
-)
-
-(define_expand "extendhisi2_mem"
- [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
- (set (match_dup 3)
- (zero_extend:SI (match_dup 7)))
- (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
- (set (match_operand:SI 0 "" "")
- (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
- "TARGET_ARM"
- "
- {
- rtx mem1, mem2;
- rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
-
- mem1 = change_address (operands[1], QImode, addr);
- mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[1] = mem1;
- operands[2] = gen_reg_rtx (SImode);
- operands[3] = gen_reg_rtx (SImode);
- operands[6] = gen_reg_rtx (SImode);
- operands[7] = mem2;
-
- if (BYTES_BIG_ENDIAN)
- {
- operands[4] = operands[2];
- operands[5] = operands[3];
- }
- else
- {
- operands[4] = operands[3];
- operands[5] = operands[2];
- }
- }"
-)
-
-(define_insn "*arm_extendhisi2"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
- "TARGET_ARM && arm_arch4 && !arm_arch6"
- "ldr%?sh\\t%0, %1"
- [(set_attr "type" "load_byte")
- (set_attr "predicable" "yes")
- (set_attr "pool_range" "256")
- (set_attr "neg_pool_range" "244")]
-)
-
-(define_insn "*arm_extendhisi2_v6"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
- "TARGET_ARM && arm_arch6"
- "@
- sxth%?\\t%0, %1
- ldr%?sh\\t%0, %1"
- [(set_attr "type" "alu_shift,load_byte")
- (set_attr "predicable" "yes")
- (set_attr "pool_range" "*,256")
- (set_attr "neg_pool_range" "*,244")]
-)
-
-(define_insn "*arm_extendhisi2addsi"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
- (match_operand:SI 2 "s_register_operand" "r")))]
- "TARGET_ARM && arm_arch6"
- "sxtah%?\\t%0, %2, %1"
-)
-
-(define_expand "extendqihi2"
- [(set (match_dup 2)
- (ashift:SI (match_operand:QI 1 "general_operand" "")
- (const_int 24)))
- (set (match_operand:HI 0 "s_register_operand" "")
- (ashiftrt:SI (match_dup 2)
- (const_int 24)))]
- "TARGET_ARM"
- "
- {
- if (arm_arch4 && GET_CODE (operands[1]) == MEM)
- {
- emit_insn (gen_rtx_SET (VOIDmode,
- operands[0],
- gen_rtx_SIGN_EXTEND (HImode, operands[1])));
- DONE;
- }
- if (!s_register_operand (operands[1], QImode))
- operands[1] = copy_to_mode_reg (QImode, operands[1]);
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = gen_reg_rtx (SImode);
- }"
-)
-
-(define_insn "*extendqihi_insn"
- [(set (match_operand:HI 0 "s_register_operand" "=r")
- (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
- "TARGET_ARM && arm_arch4"
- "ldr%?sb\\t%0, %1"
- [(set_attr "type" "load_byte")
- (set_attr "predicable" "yes")
- (set_attr "pool_range" "256")
- (set_attr "neg_pool_range" "244")]
-)
-
-(define_expand "extendqisi2"
- [(set (match_dup 2)
- (ashift:SI (match_operand:QI 1 "general_operand" "")
- (const_int 24)))
- (set (match_operand:SI 0 "s_register_operand" "")
- (ashiftrt:SI (match_dup 2)
- (const_int 24)))]
- "TARGET_EITHER"
- "
- {
- if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
- {
- emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_SIGN_EXTEND (SImode, operands[1])));
- DONE;
- }
-
- if (!s_register_operand (operands[1], QImode))
- operands[1] = copy_to_mode_reg (QImode, operands[1]);
-
- if (arm_arch6)
- {
- emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_SIGN_EXTEND (SImode, operands[1])));
- DONE;
- }
-
- operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = gen_reg_rtx (SImode);
- }"
-)
-
-(define_insn "*arm_extendqisi"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
- "TARGET_ARM && arm_arch4 && !arm_arch6"
- "ldr%?sb\\t%0, %1"
- [(set_attr "type" "load_byte")
- (set_attr "predicable" "yes")
- (set_attr "pool_range" "256")
- (set_attr "neg_pool_range" "244")]
-)
-
-(define_insn "*arm_extendqisi_v6"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
- "TARGET_ARM && arm_arch6"
- "@
- sxtb%?\\t%0, %1
- ldr%?sb\\t%0, %1"
- [(set_attr "type" "alu_shift,load_byte")
- (set_attr "predicable" "yes")
- (set_attr "pool_range" "*,256")
- (set_attr "neg_pool_range" "*,244")]
-)
-
-(define_insn "*arm_extendqisi2addsi"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
- (match_operand:SI 2 "s_register_operand" "r")))]
- "TARGET_ARM && arm_arch6"
- "sxtab%?\\t%0, %2, %1"
- [(set_attr "type" "alu_shift")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*thumb_extendqisi2"
- [(set (match_operand:SI 0 "register_operand" "=l,l")
- (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
- "TARGET_THUMB && !arm_arch6"
- "*
- {
- rtx ops[3];
- rtx mem = XEXP (operands[1], 0);
-
- if (GET_CODE (mem) == CONST)
- mem = XEXP (mem, 0);
-
- if (GET_CODE (mem) == LABEL_REF)
- return \"ldr\\t%0, %1\";
-
- if (GET_CODE (mem) == PLUS
- && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
- return \"ldr\\t%0, %1\";
-
- if (which_alternative == 0)
- return \"ldrsb\\t%0, %1\";
-
- ops[0] = operands[0];
-
- if (GET_CODE (mem) == PLUS)
- {
- rtx a = XEXP (mem, 0);
- rtx b = XEXP (mem, 1);
-
- ops[1] = a;
- ops[2] = b;
-
- if (GET_CODE (a) == REG)
- {
- if (GET_CODE (b) == REG)
- output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
- else if (REGNO (a) == REGNO (ops[0]))
- {
- output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
- output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
- output_asm_insn (\"asr\\t%0, %0, #24\", ops);
- }
- else
- output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
- }
- else
- {
- gcc_assert (GET_CODE (b) == REG);
- if (REGNO (b) == REGNO (ops[0]))
- {
- output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
- output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
- output_asm_insn (\"asr\\t%0, %0, #24\", ops);
- }
- else
- output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
- }
- }
- else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
- {
- output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
- output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
- output_asm_insn (\"asr\\t%0, %0, #24\", ops);
- }
- else
- {
- ops[1] = mem;
- ops[2] = const0_rtx;
-
- output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
- }
- return \"\";
- }"
- [(set_attr "length" "2,6")
- (set_attr "type" "load_byte,load_byte")
- (set_attr "pool_range" "32,32")]
-)
-
-(define_insn "*thumb_extendqisi2_v6"
- [(set (match_operand:SI 0 "register_operand" "=l,l,l")
- (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
- "TARGET_THUMB && arm_arch6"
- "*
- {
- rtx ops[3];
- rtx mem;
-
- if (which_alternative == 0)
- return \"sxtb\\t%0, %1\";
-
- mem = XEXP (operands[1], 0);
-
- if (GET_CODE (mem) == CONST)
- mem = XEXP (mem, 0);
-
- if (GET_CODE (mem) == LABEL_REF)
- return \"ldr\\t%0, %1\";
-
- if (GET_CODE (mem) == PLUS
- && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
- return \"ldr\\t%0, %1\";
-
- if (which_alternative == 0)
- return \"ldrsb\\t%0, %1\";
-
- ops[0] = operands[0];
-
- if (GET_CODE (mem) == PLUS)
- {
- rtx a = XEXP (mem, 0);
- rtx b = XEXP (mem, 1);
-
- ops[1] = a;
- ops[2] = b;
-
- if (GET_CODE (a) == REG)
- {
- if (GET_CODE (b) == REG)
- output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
- else if (REGNO (a) == REGNO (ops[0]))
- {
- output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
- output_asm_insn (\"sxtb\\t%0, %0\", ops);
- }
- else
- output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
- }
- else
- {
- gcc_assert (GET_CODE (b) == REG);
- if (REGNO (b) == REGNO (ops[0]))
- {
- output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
- output_asm_insn (\"sxtb\\t%0, %0\", ops);
- }
- else
- output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
- }
- }
- else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
- {
- output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
- output_asm_insn (\"sxtb\\t%0, %0\", ops);
- }
- else
- {
- ops[1] = mem;
- ops[2] = const0_rtx;
-
- output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
- }
- return \"\";
- }"
- [(set_attr "length" "2,2,4")
- (set_attr "type" "alu_shift,load_byte,load_byte")
- (set_attr "pool_range" "*,32,32")]
-)
-
-(define_expand "extendsfdf2"
- [(set (match_operand:DF 0 "s_register_operand" "")
- (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- ""
-)
-
-;; Move insns (including loads and stores)
-
-;; XXX Just some ideas about movti.
-;; I don't think these are a good idea on the arm, there just aren't enough
-;; registers
-;;(define_expand "loadti"
-;; [(set (match_operand:TI 0 "s_register_operand" "")
-;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
-;; "" "")
-
-;;(define_expand "storeti"
-;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
-;; (match_operand:TI 1 "s_register_operand" ""))]
-;; "" "")
-
-;;(define_expand "movti"
-;; [(set (match_operand:TI 0 "general_operand" "")
-;; (match_operand:TI 1 "general_operand" ""))]
-;; ""
-;; "
-;;{
-;; rtx insn;
-;;
-;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
-;; operands[1] = copy_to_reg (operands[1]);
-;; if (GET_CODE (operands[0]) == MEM)
-;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
-;; else if (GET_CODE (operands[1]) == MEM)
-;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
-;; else
-;; FAIL;
-;;
-;; emit_insn (insn);
-;; DONE;
-;;}")
-
-;; Recognize garbage generated above.
-
-;;(define_insn ""
-;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
-;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
-;; ""
-;; "*
-;; {
-;; register mem = (which_alternative < 3);
-;; register const char *template;
-;;
-;; operands[mem] = XEXP (operands[mem], 0);
-;; switch (which_alternative)
-;; {
-;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
-;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
-;; case 2: template = \"ldmia\\t%1, %M0\"; break;
-;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
-;; case 4: template = \"stmia\\t%0!, %M1\"; break;
-;; case 5: template = \"stmia\\t%0, %M1\"; break;
-;; }
-;; output_asm_insn (template, operands);
-;; return \"\";
-;; }")
-
-(define_expand "movdi"
- [(set (match_operand:DI 0 "general_operand" "")
- (match_operand:DI 1 "general_operand" ""))]
- "TARGET_EITHER"
- "
- if (!no_new_pseudos)
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (DImode, operands[1]);
- }
- "
-)
-
-(define_insn "*arm_movdi"
- [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
- (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
- "TARGET_ARM
- && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
- && !TARGET_IWMMXT
- && ( register_operand (operands[0], DImode)
- || register_operand (operands[1], DImode))"
- "*
- switch (which_alternative)
- {
- case 0:
- case 1:
- case 2:
- return \"#\";
- default:
- return output_move_double (operands);
- }
- "
- [(set_attr "length" "8,12,16,8,8")
- (set_attr "type" "*,*,*,load2,store2")
- (set_attr "pool_range" "*,*,*,1020,*")
- (set_attr "neg_pool_range" "*,*,*,1008,*")]
-)
-
-(define_split
- [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
- (match_operand:ANY64 1 "const_double_operand" ""))]
- "TARGET_ARM
- && reload_completed
- && (arm_const_double_inline_cost (operands[1])
- <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
- [(const_int 0)]
- "
- arm_split_constant (SET, SImode, curr_insn,
- INTVAL (gen_lowpart (SImode, operands[1])),
- gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
- arm_split_constant (SET, SImode, curr_insn,
- INTVAL (gen_highpart_mode (SImode,
- GET_MODE (operands[0]),
- operands[1])),
- gen_highpart (SImode, operands[0]), NULL_RTX, 0);
- DONE;
- "
-)
-
-; If optimizing for size, or if we have load delay slots, then
-; we want to split the constant into two separate operations.
-; In both cases this may split a trivial part into a single data op
-; leaving a single complex constant to load. We can also get longer
-; offsets in a LDR which means we get better chances of sharing the pool
-; entries. Finally, we can normally do a better job of scheduling
-; LDR instructions than we can with LDM.
-; This pattern will only match if the one above did not.
-(define_split
- [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
- (match_operand:ANY64 1 "const_double_operand" ""))]
- "TARGET_ARM && reload_completed
- && arm_const_double_by_parts (operands[1])"
- [(set (match_dup 0) (match_dup 1))
- (set (match_dup 2) (match_dup 3))]
- "
- operands[2] = gen_highpart (SImode, operands[0]);
- operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
- operands[1]);
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- "
-)
-
-(define_split
- [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
- (match_operand:ANY64 1 "arm_general_register_operand" ""))]
- "TARGET_EITHER && reload_completed"
- [(set (match_dup 0) (match_dup 1))
- (set (match_dup 2) (match_dup 3))]
- "
- operands[2] = gen_highpart (SImode, operands[0]);
- operands[3] = gen_highpart (SImode, operands[1]);
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[1] = gen_lowpart (SImode, operands[1]);
-
- /* Handle a partial overlap. */
- if (rtx_equal_p (operands[0], operands[3]))
- {
- rtx tmp0 = operands[0];
- rtx tmp1 = operands[1];
-
- operands[0] = operands[2];
- operands[1] = operands[3];
- operands[2] = tmp0;
- operands[3] = tmp1;
- }
- "
-)
-
-;; We can't actually do base+index doubleword loads if the index and
-;; destination overlap. Split here so that we at least have chance to
-;; schedule.
-(define_split
- [(set (match_operand:DI 0 "s_register_operand" "")
- (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "s_register_operand" ""))))]
- "TARGET_LDRD
- && reg_overlap_mentioned_p (operands[0], operands[1])
- && reg_overlap_mentioned_p (operands[0], operands[2])"
- [(set (match_dup 4)
- (plus:SI (match_dup 1)
- (match_dup 2)))
- (set (match_dup 0)
- (mem:DI (match_dup 4)))]
- "
- operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
- "
-)
-
-;;; ??? 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 "*thumb_movdi_insn"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
- (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
- "TARGET_THUMB
- && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
- && ( register_operand (operands[0], DImode)
- || register_operand (operands[1], DImode))"
- "*
- {
- switch (which_alternative)
- {
- default:
- 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")
- (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
- (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
-)
-
-(define_expand "movsi"
- [(set (match_operand:SI 0 "general_operand" "")
- (match_operand:SI 1 "general_operand" ""))]
- "TARGET_EITHER"
- "
- if (TARGET_ARM)
- {
- /* Everything except mem = const or mem = mem can be done easily. */
- if (GET_CODE (operands[0]) == MEM)
- operands[1] = force_reg (SImode, operands[1]);
- if (arm_general_register_operand (operands[0], SImode)
- && GET_CODE (operands[1]) == CONST_INT
- && !(const_ok_for_arm (INTVAL (operands[1]))
- || const_ok_for_arm (~INTVAL (operands[1]))))
- {
- arm_split_constant (SET, SImode, NULL_RTX,
- INTVAL (operands[1]), operands[0], NULL_RTX,
- optimize && !no_new_pseudos);
- DONE;
- }
- }
- else /* TARGET_THUMB.... */
- {
- if (!no_new_pseudos)
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (SImode, operands[1]);
- }
- }
-
- /* Recognize the case where operand[1] is a reference to thread-local
- data and load its address to a register. */
- if (arm_tls_referenced_p (operands[1]))
- {
- rtx tmp = operands[1];
- rtx addend = NULL;
-
- if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
- {
- addend = XEXP (XEXP (tmp, 0), 1);
- tmp = XEXP (XEXP (tmp, 0), 0);
- }
-
- gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
- gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
-
- tmp = legitimize_tls_address (tmp, no_new_pseudos ? operands[0] : 0);
- if (addend)
- {
- tmp = gen_rtx_PLUS (SImode, tmp, addend);
- tmp = force_operand (tmp, operands[0]);
- }
- operands[1] = tmp;
- }
- else if (flag_pic
- && (CONSTANT_P (operands[1])
- || symbol_mentioned_p (operands[1])
- || label_mentioned_p (operands[1])))
- operands[1] = legitimize_pic_address (operands[1], SImode,
- (no_new_pseudos ? operands[0] : 0));
- "
-)
-
-(define_insn "*arm_movsi_insn"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
- (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
- "TARGET_ARM && ! TARGET_IWMMXT
- && !(TARGET_HARD_FLOAT && TARGET_VFP)
- && ( register_operand (operands[0], SImode)
- || register_operand (operands[1], SImode))"
- "@
- mov%?\\t%0, %1
- mvn%?\\t%0, #%B1
- ldr%?\\t%0, %1
- str%?\\t%1, %0"
- [(set_attr "type" "*,*,load1,store1")
- (set_attr "predicable" "yes")
- (set_attr "pool_range" "*,*,4096,*")
- (set_attr "neg_pool_range" "*,*,4084,*")]
-)
-
-(define_split
- [(set (match_operand:SI 0 "arm_general_register_operand" "")
- (match_operand:SI 1 "const_int_operand" ""))]
- "TARGET_ARM
- && (!(const_ok_for_arm (INTVAL (operands[1]))
- || const_ok_for_arm (~INTVAL (operands[1]))))"
- [(clobber (const_int 0))]
- "
- arm_split_constant (SET, SImode, NULL_RTX,
- INTVAL (operands[1]), operands[0], NULL_RTX, 0);
- DONE;
- "
-)
-
-(define_insn "*thumb_movsi_insn"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
- (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
- "TARGET_THUMB
- && ( register_operand (operands[0], SImode)
- || register_operand (operands[1], SImode))"
- "@
- mov %0, %1
- mov %0, %1
- #
- #
- ldmia\\t%1, {%0}
- stmia\\t%0, {%1}
- ldr\\t%0, %1
- str\\t%1, %0
- mov\\t%0, %1"
- [(set_attr "length" "2,2,4,4,2,2,2,2,2")
- (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
- (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
-)
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "const_int_operand" ""))]
- "TARGET_THUMB && satisfies_constraint_J (operands[1])"
- [(set (match_dup 0) (match_dup 1))
- (set (match_dup 0) (neg:SI (match_dup 0)))]
- "operands[1] = GEN_INT (- INTVAL (operands[1]));"
-)
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "const_int_operand" ""))]
- "TARGET_THUMB && satisfies_constraint_K (operands[1])"
- [(set (match_dup 0) (match_dup 1))
- (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
- "
- {
- unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
- unsigned HOST_WIDE_INT mask = 0xff;
- int i;
-
- for (i = 0; i < 25; i++)
- if ((val & (mask << i)) == val)
- break;
-
- /* Shouldn't happen, but we don't want to split if the shift is zero. */
- if (i == 0)
- FAIL;
-
- operands[1] = GEN_INT (val >> i);
- operands[2] = GEN_INT (i);
- }"
-)
-
-;; When generating pic, we need to load the symbol offset into a register.
-;; So that the optimizer does not confuse this with a normal symbol load
-;; we use an unspec. The offset will be loaded from a constant pool entry,
-;; since that is the only type of relocation we can use.
-
-;; The rather odd constraints on the following are to force reload to leave
-;; the insn alone, and to force the minipool generation pass to then move
-;; the GOT symbol to memory.
-
-(define_insn "pic_load_addr_arm"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
- "TARGET_ARM && flag_pic"
- "ldr%?\\t%0, %1"
- [(set_attr "type" "load1")
- (set (attr "pool_range") (const_int 4096))
- (set (attr "neg_pool_range") (const_int 4084))]
-)
-
-(define_insn "pic_load_addr_thumb"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
- "TARGET_THUMB && flag_pic"
- "ldr\\t%0, %1"
- [(set_attr "type" "load1")
- (set (attr "pool_range") (const_int 1024))]
-)
-
-;; This variant is used for AOF assembly, since it needs to mention the
-;; pic register in the rtl.
-(define_expand "pic_load_addr_based"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
- "TARGET_ARM && flag_pic"
- "operands[2] = cfun->machine->pic_reg;"
-)
-
-(define_insn "*pic_load_addr_based_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (unspec:SI [(match_operand 1 "" "")
- (match_operand 2 "s_register_operand" "r")]
- UNSPEC_PIC_SYM))]
- "TARGET_EITHER && flag_pic && operands[2] == cfun->machine->pic_reg"
- "*
-#ifdef AOF_ASSEMBLER
- operands[1] = aof_pic_entry (operands[1]);
-#endif
- output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
- return \"\";
- "
- [(set_attr "type" "load1")
- (set (attr "pool_range")
- (if_then_else (eq_attr "is_thumb" "yes")
- (const_int 1024)
- (const_int 4096)))
- (set (attr "neg_pool_range")
- (if_then_else (eq_attr "is_thumb" "yes")
- (const_int 0)
- (const_int 4084)))]
-)
-
-(define_insn "pic_add_dot_plus_four"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0")
- (const (plus:SI (pc) (const_int 4))))]
- UNSPEC_PIC_BASE))
- (use (match_operand 2 "" ""))]
- "TARGET_THUMB"
- "*
- (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
- INTVAL (operands[2]));
- return \"add\\t%0, %|pc\";
- "
- [(set_attr "length" "2")]
-)
-
-(define_insn "pic_add_dot_plus_eight"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
- (const (plus:SI (pc) (const_int 8))))]
- UNSPEC_PIC_BASE))
- (use (match_operand 2 "" ""))]
- "TARGET_ARM"
- "*
- (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
- INTVAL (operands[2]));
- return \"add%?\\t%0, %|pc, %1\";
- "
- [(set_attr "predicable" "yes")]
-)
-
-(define_insn "tls_load_dot_plus_eight"
- [(set (match_operand:SI 0 "register_operand" "+r")
- (mem:SI (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
- (const (plus:SI (pc) (const_int 8))))]
- UNSPEC_PIC_BASE)))
- (use (match_operand 2 "" ""))]
- "TARGET_ARM"
- "*
- (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
- INTVAL (operands[2]));
- return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
- "
- [(set_attr "predicable" "yes")]
-)
-
-;; PIC references to local variables can generate pic_add_dot_plus_eight
-;; followed by a load. These sequences can be crunched down to
-;; tls_load_dot_plus_eight by a peephole.
-
-(define_peephole2
- [(parallel [(set (match_operand:SI 0 "register_operand" "")
- (unspec:SI [(plus:SI (match_operand:SI 3 "register_operand" "")
- (const (plus:SI (pc) (const_int 8))))]
- UNSPEC_PIC_BASE))
- (use (label_ref (match_operand 1 "" "")))])
- (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
- "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
- [(parallel [(set (match_dup 2)
- (mem:SI (unspec:SI [(plus:SI (match_dup 3)
- (const (plus:SI (pc) (const_int 8))))]
- UNSPEC_PIC_BASE)))
- (use (label_ref (match_dup 1)))])]
- ""
-)
-
-(define_expand "builtin_setjmp_receiver"
- [(label_ref (match_operand 0 "" ""))]
- "flag_pic"
- "
-{
- /* r3 is clobbered by set/longjmp, so we can use it as a scratch
- register. */
- if (arm_pic_register != INVALID_REGNUM)
- arm_load_pic_register (1UL << 3);
- DONE;
-}")
-
-;; If copying one reg to another we can set the condition codes according to
-;; its value. Such a move is common after a return from subroutine and the
-;; result is being tested against zero.
-
-(define_insn "*movsi_compare0"
- [(set (reg:CC CC_REGNUM)
- (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
- (const_int 0)))
- (set (match_operand:SI 0 "s_register_operand" "=r,r")
- (match_dup 1))]
- "TARGET_ARM"
- "@
- cmp%?\\t%0, #0
- sub%?s\\t%0, %1, #0"
- [(set_attr "conds" "set")]
-)
-
-;; Subroutine to store a half word from a register into memory.
-;; Operand 0 is the source register (HImode)
-;; Operand 1 is the destination address in a register (SImode)
-
-;; In both this routine and the next, we must be careful not to spill
-;; a memory address of reg+large_const into a separate PLUS insn, since this
-;; can generate unrecognizable rtl.
-
-(define_expand "storehi"
- [;; store the low byte
- (set (match_operand 1 "" "") (match_dup 3))
- ;; extract the high byte
- (set (match_dup 2)
- (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
- ;; store the high byte
- (set (match_dup 4) (match_dup 5))]
- "TARGET_ARM"
- "
- {
- rtx op1 = operands[1];
- rtx addr = XEXP (op1, 0);
- enum rtx_code code = GET_CODE (addr);
-
- if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
- || code == MINUS)
- op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
-
- operands[4] = adjust_address (op1, QImode, 1);
- operands[1] = adjust_address (operands[1], QImode, 0);
- operands[3] = gen_lowpart (QImode, operands[0]);
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[2] = gen_reg_rtx (SImode);
- operands[5] = gen_lowpart (QImode, operands[2]);
- }"
-)
-
-(define_expand "storehi_bigend"
- [(set (match_dup 4) (match_dup 3))
- (set (match_dup 2)
- (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
- (set (match_operand 1 "" "") (match_dup 5))]
- "TARGET_ARM"
- "
- {
- rtx op1 = operands[1];
- rtx addr = XEXP (op1, 0);
- enum rtx_code code = GET_CODE (addr);
-
- if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
- || code == MINUS)
- op1 = replace_equiv_address (op1, force_reg (SImode, addr));
-
- operands[4] = adjust_address (op1, QImode, 1);
- operands[1] = adjust_address (operands[1], QImode, 0);
- operands[3] = gen_lowpart (QImode, operands[0]);
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[2] = gen_reg_rtx (SImode);
- operands[5] = gen_lowpart (QImode, operands[2]);
- }"
-)
-
-;; Subroutine to store a half word integer constant into memory.
-(define_expand "storeinthi"
- [(set (match_operand 0 "" "")
- (match_operand 1 "" ""))
- (set (match_dup 3) (match_dup 2))]
- "TARGET_ARM"
- "
- {
- HOST_WIDE_INT value = INTVAL (operands[1]);
- rtx addr = XEXP (operands[0], 0);
- rtx op0 = operands[0];
- enum rtx_code code = GET_CODE (addr);
-
- if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
- || code == MINUS)
- op0 = replace_equiv_address (op0, force_reg (SImode, addr));
-
- operands[1] = gen_reg_rtx (SImode);
- if (BYTES_BIG_ENDIAN)
- {
- emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
- if ((value & 255) == ((value >> 8) & 255))
- operands[2] = operands[1];
- else
- {
- operands[2] = gen_reg_rtx (SImode);
- emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
- }
- }
- else
- {
- emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
- if ((value & 255) == ((value >> 8) & 255))
- operands[2] = operands[1];
- else
- {
- operands[2] = gen_reg_rtx (SImode);
- emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
- }
- }
-
- operands[3] = adjust_address (op0, QImode, 1);
- operands[0] = adjust_address (operands[0], QImode, 0);
- operands[2] = gen_lowpart (QImode, operands[2]);
- operands[1] = gen_lowpart (QImode, operands[1]);
- }"
-)
-
-(define_expand "storehi_single_op"
- [(set (match_operand:HI 0 "memory_operand" "")
- (match_operand:HI 1 "general_operand" ""))]
- "TARGET_ARM && arm_arch4"
- "
- if (!s_register_operand (operands[1], HImode))
- operands[1] = copy_to_mode_reg (HImode, operands[1]);
- "
-)
-
-(define_expand "movhi"
- [(set (match_operand:HI 0 "general_operand" "")
- (match_operand:HI 1 "general_operand" ""))]
- "TARGET_EITHER"
- "
- if (TARGET_ARM)
- {
- if (!no_new_pseudos)
- {
- if (GET_CODE (operands[0]) == MEM)
- {
- if (arm_arch4)
- {
- emit_insn (gen_storehi_single_op (operands[0], operands[1]));
- DONE;
- }
- if (GET_CODE (operands[1]) == CONST_INT)
- emit_insn (gen_storeinthi (operands[0], operands[1]));
- else
- {
- if (GET_CODE (operands[1]) == MEM)
- operands[1] = force_reg (HImode, operands[1]);
- if (BYTES_BIG_ENDIAN)
- emit_insn (gen_storehi_bigend (operands[1], operands[0]));
- else
- emit_insn (gen_storehi (operands[1], operands[0]));
- }
- DONE;
- }
- /* Sign extend a constant, and keep it in an SImode reg. */
- else if (GET_CODE (operands[1]) == CONST_INT)
- {
- rtx reg = gen_reg_rtx (SImode);
- HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
-
- /* If the constant is already valid, leave it alone. */
- if (!const_ok_for_arm (val))
- {
- /* If setting all the top bits will make the constant
- loadable in a single instruction, then set them.
- Otherwise, sign extend the number. */
-
- if (const_ok_for_arm (~(val | ~0xffff)))
- val |= ~0xffff;
- else if (val & 0x8000)
- val |= ~0xffff;
- }
-
- emit_insn (gen_movsi (reg, GEN_INT (val)));
- operands[1] = gen_lowpart (HImode, reg);
- }
- else if (arm_arch4 && optimize && !no_new_pseudos
- && GET_CODE (operands[1]) == MEM)
- {
- rtx reg = gen_reg_rtx (SImode);
-
- emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
- operands[1] = gen_lowpart (HImode, reg);
- }
- else if (!arm_arch4)
- {
- if (GET_CODE (operands[1]) == MEM)
- {
- rtx base;
- rtx offset = const0_rtx;
- rtx reg = gen_reg_rtx (SImode);
-
- if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
- || (GET_CODE (base) == PLUS
- && (GET_CODE (offset = XEXP (base, 1))
- == CONST_INT)
- && ((INTVAL(offset) & 1) != 1)
- && GET_CODE (base = XEXP (base, 0)) == REG))
- && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
- {
- rtx new;
-
- new = widen_memory_access (operands[1], SImode,
- ((INTVAL (offset) & ~3)
- - INTVAL (offset)));
- emit_insn (gen_movsi (reg, new));
- if (((INTVAL (offset) & 2) != 0)
- ^ (BYTES_BIG_ENDIAN ? 1 : 0))
- {
- rtx reg2 = gen_reg_rtx (SImode);
-
- emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
- reg = reg2;
- }
- }
- else
- emit_insn (gen_movhi_bytes (reg, operands[1]));
-
- operands[1] = gen_lowpart (HImode, reg);
- }
- }
- }
- /* Handle loading a large integer during reload. */
- else if (GET_CODE (operands[1]) == CONST_INT
- && !const_ok_for_arm (INTVAL (operands[1]))
- && !const_ok_for_arm (~INTVAL (operands[1])))
- {
- /* Writing a constant to memory needs a scratch, which should
- be handled with SECONDARY_RELOADs. */
- gcc_assert (GET_CODE (operands[0]) == REG);
-
- operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
- emit_insn (gen_movsi (operands[0], operands[1]));
- DONE;
- }
- }
- else /* TARGET_THUMB */
- {
- if (!no_new_pseudos)
- {
- if (GET_CODE (operands[1]) == CONST_INT)
- {
- rtx reg = gen_reg_rtx (SImode);
-
- emit_insn (gen_movsi (reg, operands[1]));
- operands[1] = gen_lowpart (HImode, reg);
- }
-
- /* ??? 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)))
- operands[0]
- = replace_equiv_address (operands[0],
- copy_to_reg (XEXP (operands[0], 0)));
-
- if (GET_CODE (operands[1]) == MEM
- && !memory_address_p (GET_MODE (operands[1]),
- XEXP (operands[1], 0)))
- operands[1]
- = replace_equiv_address (operands[1],
- copy_to_reg (XEXP (operands[1], 0)));
-
- if (GET_CODE (operands[1]) == MEM && optimize > 0)
- {
- rtx reg = gen_reg_rtx (SImode);
-
- emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
- operands[1] = gen_lowpart (HImode, reg);
- }
-
- if (GET_CODE (operands[0]) == MEM)
- operands[1] = force_reg (HImode, operands[1]);
- }
- else if (GET_CODE (operands[1]) == CONST_INT
- && !satisfies_constraint_I (operands[1]))
- {
- /* Handle loading a large integer during reload. */
-
- /* Writing a constant to memory needs a scratch, which should
- be handled with SECONDARY_RELOADs. */
- gcc_assert (GET_CODE (operands[0]) == REG);
-
- operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
- emit_insn (gen_movsi (operands[0], operands[1]));
- DONE;
- }
- }
- "
-)
-
-(define_insn "*thumb_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"))]
- "TARGET_THUMB
- && ( register_operand (operands[0], HImode)
- || register_operand (operands[1], HImode))"
- "*
- switch (which_alternative)
- {
- case 0: return \"add %0, %1, #0\";
- case 2: return \"strh %1, %0\";
- case 3: return \"mov %0, %1\";
- case 4: return \"mov %0, %1\";
- case 5: return \"mov %0, %1\";
- default: gcc_unreachable ();
- case 1:
- /* The stack pointer can end up being taken as an index register.
- Catch this case here and deal with it. */
- if (GET_CODE (XEXP (operands[1], 0)) == PLUS
- && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
- && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
- {
- rtx ops[2];
- ops[0] = operands[0];
- ops[1] = XEXP (XEXP (operands[1], 0), 0);
-
- output_asm_insn (\"mov %0, %1\", ops);
-
- XEXP (XEXP (operands[1], 0), 0) = operands[0];
-
- }
- return \"ldrh %0, %1\";
- }"
- [(set_attr "length" "2,4,2,2,2,2")
- (set_attr "type" "*,load1,store1,*,*,*")]
-)
-
-
-(define_expand "movhi_bytes"
- [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
- (set (match_dup 3)
- (zero_extend:SI (match_dup 6)))
- (set (match_operand:SI 0 "" "")
- (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
- "TARGET_ARM"
- "
- {
- rtx mem1, mem2;
- rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
-
- mem1 = change_address (operands[1], QImode, addr);
- mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[1] = mem1;
- operands[2] = gen_reg_rtx (SImode);
- operands[3] = gen_reg_rtx (SImode);
- operands[6] = mem2;
-
- if (BYTES_BIG_ENDIAN)
- {
- operands[4] = operands[2];
- operands[5] = operands[3];
- }
- else
- {
- operands[4] = operands[3];
- operands[5] = operands[2];
- }
- }"
-)
-
-(define_expand "movhi_bigend"
- [(set (match_dup 2)
- (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
- (const_int 16)))
- (set (match_dup 3)
- (ashiftrt:SI (match_dup 2) (const_int 16)))
- (set (match_operand:HI 0 "s_register_operand" "")
- (match_dup 4))]
- "TARGET_ARM"
- "
- operands[2] = gen_reg_rtx (SImode);
- operands[3] = gen_reg_rtx (SImode);
- operands[4] = gen_lowpart (HImode, operands[3]);
- "
-)
-
-;; Pattern to recognize insn generated default case above
-(define_insn "*movhi_insn_arch4"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
- (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
- "TARGET_ARM
- && arm_arch4
- && (GET_CODE (operands[1]) != CONST_INT
- || const_ok_for_arm (INTVAL (operands[1]))
- || const_ok_for_arm (~INTVAL (operands[1])))"
- "@
- mov%?\\t%0, %1\\t%@ movhi
- mvn%?\\t%0, #%B1\\t%@ movhi
- str%?h\\t%1, %0\\t%@ movhi
- ldr%?h\\t%0, %1\\t%@ movhi"
- [(set_attr "type" "*,*,store1,load1")
- (set_attr "predicable" "yes")
- (set_attr "pool_range" "*,*,*,256")
- (set_attr "neg_pool_range" "*,*,*,244")]
-)
-
-(define_insn "*movhi_bytes"
- [(set (match_operand:HI 0 "s_register_operand" "=r,r")
- (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
- "TARGET_ARM"
- "@
- mov%?\\t%0, %1\\t%@ movhi
- mvn%?\\t%0, #%B1\\t%@ movhi"
- [(set_attr "predicable" "yes")]
-)
-
-(define_expand "thumb_movhi_clobber"
- [(set (match_operand:HI 0 "memory_operand" "")
- (match_operand:HI 1 "register_operand" ""))
- (clobber (match_operand:DI 2 "register_operand" ""))]
- "TARGET_THUMB"
- "
- if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
- && REGNO (operands[1]) <= LAST_LO_REGNUM)
- {
- emit_insn (gen_movhi (operands[0], operands[1]));
- DONE;
- }
- /* XXX Fixme, need to handle other cases here as well. */
- gcc_unreachable ();
- "
-)
-
-;; We use a DImode scratch because we may occasionally need an additional
-;; temporary if the address isn't offsettable -- push_reload doesn't seem
-;; to take any notice of the "o" constraints on reload_memory_operand operand.
-(define_expand "reload_outhi"
- [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
- (match_operand:HI 1 "s_register_operand" "r")
- (match_operand:DI 2 "s_register_operand" "=&l")])]
- "TARGET_EITHER"
- "if (TARGET_ARM)
- arm_reload_out_hi (operands);
- else
- thumb_reload_out_hi (operands);
- DONE;
- "
-)
-
-(define_expand "reload_inhi"
- [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
- (match_operand:HI 1 "arm_reload_memory_operand" "o")
- (match_operand:DI 2 "s_register_operand" "=&r")])]
- "TARGET_EITHER"
- "
- if (TARGET_ARM)
- arm_reload_in_hi (operands);
- else
- thumb_reload_out_hi (operands);
- DONE;
-")
-
-(define_expand "movqi"
- [(set (match_operand:QI 0 "general_operand" "")
- (match_operand:QI 1 "general_operand" ""))]
- "TARGET_EITHER"
- "
- /* Everything except mem = const or mem = mem can be done easily */
-
- if (!no_new_pseudos)
- {
- if (GET_CODE (operands[1]) == CONST_INT)
- {
- rtx reg = gen_reg_rtx (SImode);
-
- emit_insn (gen_movsi (reg, operands[1]));
- operands[1] = gen_lowpart (QImode, reg);
- }
-
- if (TARGET_THUMB)
- {
- /* ??? 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)))
- operands[0]
- = replace_equiv_address (operands[0],
- copy_to_reg (XEXP (operands[0], 0)));
- if (GET_CODE (operands[1]) == MEM
- && !memory_address_p (GET_MODE (operands[1]),
- XEXP (operands[1], 0)))
- operands[1]
- = replace_equiv_address (operands[1],
- copy_to_reg (XEXP (operands[1], 0)));
- }
-
- if (GET_CODE (operands[1]) == MEM && optimize > 0)
- {
- rtx reg = gen_reg_rtx (SImode);
-
- emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
- operands[1] = gen_lowpart (QImode, reg);
- }
-
- if (GET_CODE (operands[0]) == MEM)
- operands[1] = force_reg (QImode, operands[1]);
- }
- else if (TARGET_THUMB
- && GET_CODE (operands[1]) == CONST_INT
- && !satisfies_constraint_I (operands[1]))
- {
- /* Handle loading a large integer during reload. */
-
- /* Writing a constant to memory needs a scratch, which should
- be handled with SECONDARY_RELOADs. */
- gcc_assert (GET_CODE (operands[0]) == REG);
-
- operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
- emit_insn (gen_movsi (operands[0], operands[1]));
- DONE;
- }
- "
-)
-
-
-(define_insn "*arm_movqi_insn"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
- (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
- "TARGET_ARM
- && ( register_operand (operands[0], QImode)
- || register_operand (operands[1], QImode))"
- "@
- mov%?\\t%0, %1
- mvn%?\\t%0, #%B1
- ldr%?b\\t%0, %1
- str%?b\\t%1, %0"
- [(set_attr "type" "*,*,load1,store1")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*thumb_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"))]
- "TARGET_THUMB
- && ( 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"
- [(set_attr "length" "2")
- (set_attr "type" "*,load1,store1,*,*,*")
- (set_attr "pool_range" "*,32,*,*,*,*")]
-)
-
-(define_expand "movsf"
- [(set (match_operand:SF 0 "general_operand" "")
- (match_operand:SF 1 "general_operand" ""))]
- "TARGET_EITHER"
- "
- if (TARGET_ARM)
- {
- if (GET_CODE (operands[0]) == MEM)
- operands[1] = force_reg (SFmode, operands[1]);
- }
- else /* TARGET_THUMB */
- {
- if (!no_new_pseudos)
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (SFmode, operands[1]);
- }
- }
- "
-)
-
-;; Transform a floating-point move of a constant into a core register into
-;; an SImode operation.
-(define_split
- [(set (match_operand:SF 0 "arm_general_register_operand" "")
- (match_operand:SF 1 "immediate_operand" ""))]
- "TARGET_ARM
- && reload_completed
- && GET_CODE (operands[1]) == CONST_DOUBLE"
- [(set (match_dup 2) (match_dup 3))]
- "
- operands[2] = gen_lowpart (SImode, operands[0]);
- operands[3] = gen_lowpart (SImode, operands[1]);
- if (operands[2] == 0 || operands[3] == 0)
- FAIL;
- "
-)
-
-(define_insn "*arm_movsf_soft_insn"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
- (match_operand:SF 1 "general_operand" "r,mE,r"))]
- "TARGET_ARM
- && TARGET_SOFT_FLOAT
- && (GET_CODE (operands[0]) != MEM
- || register_operand (operands[1], SFmode))"
- "@
- mov%?\\t%0, %1
- ldr%?\\t%0, %1\\t%@ float
- str%?\\t%1, %0\\t%@ float"
- [(set_attr "length" "4,4,4")
- (set_attr "predicable" "yes")
- (set_attr "type" "*,load1,store1")
- (set_attr "pool_range" "*,4096,*")
- (set_attr "neg_pool_range" "*,4084,*")]
-)
-
-;;; ??? This should have alternatives for constants.
-(define_insn "*thumb_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"))]
- "TARGET_THUMB
- && ( 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"
- [(set_attr "length" "2")
- (set_attr "type" "*,load1,store1,load1,store1,*,*")
- (set_attr "pool_range" "*,*,*,1020,*,*,*")]
-)
-
-(define_expand "movdf"
- [(set (match_operand:DF 0 "general_operand" "")
- (match_operand:DF 1 "general_operand" ""))]
- "TARGET_EITHER"
- "
- if (TARGET_ARM)
- {
- if (GET_CODE (operands[0]) == MEM)
- operands[1] = force_reg (DFmode, operands[1]);
- }
- else /* TARGET_THUMB */
- {
- if (!no_new_pseudos)
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (DFmode, operands[1]);
- }
- }
- "
-)
-
-;; Reloading a df mode value stored in integer regs to memory can require a
-;; scratch reg.
-(define_expand "reload_outdf"
- [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
- (match_operand:DF 1 "s_register_operand" "r")
- (match_operand:SI 2 "s_register_operand" "=&r")]
- "TARGET_ARM"
- "
- {
- enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
-
- if (code == REG)
- operands[2] = XEXP (operands[0], 0);
- else if (code == POST_INC || code == PRE_DEC)
- {
- operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
- operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
- emit_insn (gen_movdi (operands[0], operands[1]));
- DONE;
- }
- else if (code == PRE_INC)
- {
- rtx reg = XEXP (XEXP (operands[0], 0), 0);
-
- emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
- operands[2] = reg;
- }
- else if (code == POST_DEC)
- operands[2] = XEXP (XEXP (operands[0], 0), 0);
- else
- emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
- XEXP (XEXP (operands[0], 0), 1)));
-
- emit_insn (gen_rtx_SET (VOIDmode,
- replace_equiv_address (operands[0], operands[2]),
- operands[1]));
-
- if (code == POST_DEC)
- emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
-
- DONE;
- }"
-)
-
-(define_insn "*movdf_soft_insn"
- [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
- (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
- "TARGET_ARM && TARGET_SOFT_FLOAT
- && ( register_operand (operands[0], DFmode)
- || register_operand (operands[1], DFmode))"
- "*
- switch (which_alternative)
- {
- case 0:
- case 1:
- case 2:
- return \"#\";
- default:
- return output_move_double (operands);
- }
- "
- [(set_attr "length" "8,12,16,8,8")
- (set_attr "type" "*,*,*,load2,store2")
- (set_attr "pool_range" "1020")
- (set_attr "neg_pool_range" "1008")]
-)
-
-;;; ??? 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 "*thumb_movdf_insn"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
- (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
- "TARGET_THUMB
- && ( register_operand (operands[0], DFmode)
- || register_operand (operands[1], DFmode))"
- "*
- switch (which_alternative)
- {
- default:
- 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")
- (set_attr "type" "*,load2,store2,load2,store2,*")
- (set_attr "pool_range" "*,*,*,1020,*,*")]
-)
-
-(define_expand "movxf"
- [(set (match_operand:XF 0 "general_operand" "")
- (match_operand:XF 1 "general_operand" ""))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "
- if (GET_CODE (operands[0]) == MEM)
- operands[1] = force_reg (XFmode, operands[1]);
- "
-)
-
-;; Vector Moves
-(define_expand "movv2si"
- [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
- (match_operand:V2SI 1 "general_operand" ""))]
- "TARGET_REALLY_IWMMXT"
-{
-})
-
-(define_expand "movv4hi"
- [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
- (match_operand:V4HI 1 "general_operand" ""))]
- "TARGET_REALLY_IWMMXT"
-{
-})
-
-(define_expand "movv8qi"
- [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
- (match_operand:V8QI 1 "general_operand" ""))]
- "TARGET_REALLY_IWMMXT"
-{
-})
-
-
-;; load- and store-multiple insns
-;; The arm can load/store any set of registers, provided that they are in
-;; ascending order; but that is beyond GCC so stick with what it knows.
-
-(define_expand "load_multiple"
- [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
- (match_operand:SI 1 "" ""))
- (use (match_operand:SI 2 "" ""))])]
- "TARGET_ARM"
-{
- HOST_WIDE_INT offset = 0;
-
- /* Support only fixed point registers. */
- if (GET_CODE (operands[2]) != CONST_INT
- || INTVAL (operands[2]) > 14
- || INTVAL (operands[2]) < 2
- || GET_CODE (operands[1]) != MEM
- || GET_CODE (operands[0]) != REG
- || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
- || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
- FAIL;
-
- operands[3]
- = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
- force_reg (SImode, XEXP (operands[1], 0)),
- TRUE, FALSE, operands[1], &offset);
-})
-
-;; Load multiple with write-back
-
-(define_insn "*ldmsi_postinc4"
- [(match_parallel 0 "load_multiple_operation"
- [(set (match_operand:SI 1 "s_register_operand" "=r")
- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
- (const_int 16)))
- (set (match_operand:SI 3 "arm_hard_register_operand" "")
- (mem:SI (match_dup 2)))
- (set (match_operand:SI 4 "arm_hard_register_operand" "")
- (mem:SI (plus:SI (match_dup 2) (const_int 4))))
- (set (match_operand:SI 5 "arm_hard_register_operand" "")
- (mem:SI (plus:SI (match_dup 2) (const_int 8))))
- (set (match_operand:SI 6 "arm_hard_register_operand" "")
- (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
- "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
- "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
- [(set_attr "type" "load4")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*ldmsi_postinc4_thumb"
- [(match_parallel 0 "load_multiple_operation"
- [(set (match_operand:SI 1 "s_register_operand" "=l")
- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
- (const_int 16)))
- (set (match_operand:SI 3 "arm_hard_register_operand" "")
- (mem:SI (match_dup 2)))
- (set (match_operand:SI 4 "arm_hard_register_operand" "")
- (mem:SI (plus:SI (match_dup 2) (const_int 4))))
- (set (match_operand:SI 5 "arm_hard_register_operand" "")
- (mem:SI (plus:SI (match_dup 2) (const_int 8))))
- (set (match_operand:SI 6 "arm_hard_register_operand" "")
- (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
- "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
- "ldmia\\t%1!, {%3, %4, %5, %6}"
- [(set_attr "type" "load4")]
-)
-
-(define_insn "*ldmsi_postinc3"
- [(match_parallel 0 "load_multiple_operation"
- [(set (match_operand:SI 1 "s_register_operand" "=r")
- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
- (const_int 12)))
- (set (match_operand:SI 3 "arm_hard_register_operand" "")
- (mem:SI (match_dup 2)))
- (set (match_operand:SI 4 "arm_hard_register_operand" "")
- (mem:SI (plus:SI (match_dup 2) (const_int 4))))
- (set (match_operand:SI 5 "arm_hard_register_operand" "")
- (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
- "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
- "ldm%?ia\\t%1!, {%3, %4, %5}"
- [(set_attr "type" "load3")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*ldmsi_postinc2"
- [(match_parallel 0 "load_multiple_operation"
- [(set (match_operand:SI 1 "s_register_operand" "=r")
- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
- (const_int 8)))
- (set (match_operand:SI 3 "arm_hard_register_operand" "")
- (mem:SI (match_dup 2)))
- (set (match_operand:SI 4 "arm_hard_register_operand" "")
- (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
- "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
- "ldm%?ia\\t%1!, {%3, %4}"
- [(set_attr "type" "load2")
- (set_attr "predicable" "yes")]
-)
-
-;; Ordinary load multiple
-
-(define_insn "*ldmsi4"
- [(match_parallel 0 "load_multiple_operation"
- [(set (match_operand:SI 2 "arm_hard_register_operand" "")
- (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
- (set (match_operand:SI 3 "arm_hard_register_operand" "")
- (mem:SI (plus:SI (match_dup 1) (const_int 4))))
- (set (match_operand:SI 4 "arm_hard_register_operand" "")
- (mem:SI (plus:SI (match_dup 1) (const_int 8))))
- (set (match_operand:SI 5 "arm_hard_register_operand" "")
- (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
- "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
- "ldm%?ia\\t%1, {%2, %3, %4, %5}"
- [(set_attr "type" "load4")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*ldmsi3"
- [(match_parallel 0 "load_multiple_operation"
- [(set (match_operand:SI 2 "arm_hard_register_operand" "")
- (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
- (set (match_operand:SI 3 "arm_hard_register_operand" "")
- (mem:SI (plus:SI (match_dup 1) (const_int 4))))
- (set (match_operand:SI 4 "arm_hard_register_operand" "")
- (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
- "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
- "ldm%?ia\\t%1, {%2, %3, %4}"
- [(set_attr "type" "load3")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*ldmsi2"
- [(match_parallel 0 "load_multiple_operation"
- [(set (match_operand:SI 2 "arm_hard_register_operand" "")
- (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
- (set (match_operand:SI 3 "arm_hard_register_operand" "")
- (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
- "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
- "ldm%?ia\\t%1, {%2, %3}"
- [(set_attr "type" "load2")
- (set_attr "predicable" "yes")]
-)
-
-(define_expand "store_multiple"
- [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
- (match_operand:SI 1 "" ""))
- (use (match_operand:SI 2 "" ""))])]
- "TARGET_ARM"
-{
- HOST_WIDE_INT offset = 0;
-
- /* Support only fixed point registers. */
- if (GET_CODE (operands[2]) != CONST_INT
- || INTVAL (operands[2]) > 14
- || INTVAL (operands[2]) < 2
- || GET_CODE (operands[1]) != REG
- || GET_CODE (operands[0]) != MEM
- || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
- || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
- FAIL;
-
- operands[3]
- = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
- force_reg (SImode, XEXP (operands[0], 0)),
- TRUE, FALSE, operands[0], &offset);
-})
-
-;; Store multiple with write-back
-
-(define_insn "*stmsi_postinc4"
- [(match_parallel 0 "store_multiple_operation"
- [(set (match_operand:SI 1 "s_register_operand" "=r")
- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
- (const_int 16)))
- (set (mem:SI (match_dup 2))
- (match_operand:SI 3 "arm_hard_register_operand" ""))
- (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
- (match_operand:SI 4 "arm_hard_register_operand" ""))
- (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
- (match_operand:SI 5 "arm_hard_register_operand" ""))
- (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
- (match_operand:SI 6 "arm_hard_register_operand" ""))])]
- "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
- "stm%?ia\\t%1!, {%3, %4, %5, %6}"
- [(set_attr "predicable" "yes")
- (set_attr "type" "store4")]
-)
-
-(define_insn "*stmsi_postinc4_thumb"
- [(match_parallel 0 "store_multiple_operation"
- [(set (match_operand:SI 1 "s_register_operand" "=l")
- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
- (const_int 16)))
- (set (mem:SI (match_dup 2))
- (match_operand:SI 3 "arm_hard_register_operand" ""))
- (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
- (match_operand:SI 4 "arm_hard_register_operand" ""))
- (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
- (match_operand:SI 5 "arm_hard_register_operand" ""))
- (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
- (match_operand:SI 6 "arm_hard_register_operand" ""))])]
- "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
- "stmia\\t%1!, {%3, %4, %5, %6}"
- [(set_attr "type" "store4")]
-)
-
-(define_insn "*stmsi_postinc3"
- [(match_parallel 0 "store_multiple_operation"
- [(set (match_operand:SI 1 "s_register_operand" "=r")
- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
- (const_int 12)))
- (set (mem:SI (match_dup 2))
- (match_operand:SI 3 "arm_hard_register_operand" ""))
- (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
- (match_operand:SI 4 "arm_hard_register_operand" ""))
- (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
- (match_operand:SI 5 "arm_hard_register_operand" ""))])]
- "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
- "stm%?ia\\t%1!, {%3, %4, %5}"
- [(set_attr "predicable" "yes")
- (set_attr "type" "store3")]
-)
-
-(define_insn "*stmsi_postinc2"
- [(match_parallel 0 "store_multiple_operation"
- [(set (match_operand:SI 1 "s_register_operand" "=r")
- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
- (const_int 8)))
- (set (mem:SI (match_dup 2))
- (match_operand:SI 3 "arm_hard_register_operand" ""))
- (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
- (match_operand:SI 4 "arm_hard_register_operand" ""))])]
- "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
- "stm%?ia\\t%1!, {%3, %4}"
- [(set_attr "predicable" "yes")
- (set_attr "type" "store2")]
-)
-
-;; Ordinary store multiple
-
-(define_insn "*stmsi4"
- [(match_parallel 0 "store_multiple_operation"
- [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
- (match_operand:SI 2 "arm_hard_register_operand" ""))
- (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
- (match_operand:SI 3 "arm_hard_register_operand" ""))
- (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
- (match_operand:SI 4 "arm_hard_register_operand" ""))
- (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
- (match_operand:SI 5 "arm_hard_register_operand" ""))])]
- "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
- "stm%?ia\\t%1, {%2, %3, %4, %5}"
- [(set_attr "predicable" "yes")
- (set_attr "type" "store4")]
-)
-
-(define_insn "*stmsi3"
- [(match_parallel 0 "store_multiple_operation"
- [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
- (match_operand:SI 2 "arm_hard_register_operand" ""))
- (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
- (match_operand:SI 3 "arm_hard_register_operand" ""))
- (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
- (match_operand:SI 4 "arm_hard_register_operand" ""))])]
- "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
- "stm%?ia\\t%1, {%2, %3, %4}"
- [(set_attr "predicable" "yes")
- (set_attr "type" "store3")]
-)
-
-(define_insn "*stmsi2"
- [(match_parallel 0 "store_multiple_operation"
- [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
- (match_operand:SI 2 "arm_hard_register_operand" ""))
- (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
- (match_operand:SI 3 "arm_hard_register_operand" ""))])]
- "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
- "stm%?ia\\t%1, {%2, %3}"
- [(set_attr "predicable" "yes")
- (set_attr "type" "store2")]
-)
-
-;; Move a block of memory if it is word aligned and MORE than 2 words long.
-;; We could let this apply for blocks of less than this, but it clobbers so
-;; many registers that there is then probably a better way.
-
-(define_expand "movmemqi"
- [(match_operand:BLK 0 "general_operand" "")
- (match_operand:BLK 1 "general_operand" "")
- (match_operand:SI 2 "const_int_operand" "")
- (match_operand:SI 3 "const_int_operand" "")]
- "TARGET_EITHER"
- "
- if (TARGET_ARM)
- {
- if (arm_gen_movmemqi (operands))
- DONE;
- FAIL;
- }
- else /* TARGET_THUMB */
- {
- if ( INTVAL (operands[3]) != 4
- || INTVAL (operands[2]) > 48)
- FAIL;
-
- thumb_expand_movmemqi (operands);
- DONE;
- }
- "
-)
-
-;; Thumb block-move insns
-
-(define_insn "movmem12b"
- [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
- (mem:SI (match_operand:SI 3 "register_operand" "1")))
- (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
- (mem:SI (plus:SI (match_dup 3) (const_int 4))))
- (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
- (mem:SI (plus:SI (match_dup 3) (const_int 8))))
- (set (match_operand:SI 0 "register_operand" "=l")
- (plus:SI (match_dup 2) (const_int 12)))
- (set (match_operand:SI 1 "register_operand" "=l")
- (plus:SI (match_dup 3) (const_int 12)))
- (clobber (match_scratch:SI 4 "=&l"))
- (clobber (match_scratch:SI 5 "=&l"))
- (clobber (match_scratch:SI 6 "=&l"))]
- "TARGET_THUMB"
- "* return thumb_output_move_mem_multiple (3, operands);"
- [(set_attr "length" "4")
- ; This isn't entirely accurate... It loads as well, but in terms of
- ; scheduling the following insn it is better to consider it as a store
- (set_attr "type" "store3")]
-)
-
-(define_insn "movmem8b"
- [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
- (mem:SI (match_operand:SI 3 "register_operand" "1")))
- (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
- (mem:SI (plus:SI (match_dup 3) (const_int 4))))
- (set (match_operand:SI 0 "register_operand" "=l")
- (plus:SI (match_dup 2) (const_int 8)))
- (set (match_operand:SI 1 "register_operand" "=l")
- (plus:SI (match_dup 3) (const_int 8)))
- (clobber (match_scratch:SI 4 "=&l"))
- (clobber (match_scratch:SI 5 "=&l"))]
- "TARGET_THUMB"
- "* return thumb_output_move_mem_multiple (2, operands);"
- [(set_attr "length" "4")
- ; This isn't entirely accurate... It loads as well, but in terms of
- ; scheduling the following insn it is better to consider it as a store
- (set_attr "type" "store2")]
-)
-
-
-
-;; Compare & branch insns
-;; The range calculations are based as follows:
-;; For forward branches, the address calculation returns the address of
-;; the next instruction. This is 2 beyond the branch instruction.
-;; For backward branches, the address calculation returns the address of
-;; the first instruction in this pattern (cmp). This is 2 before the branch
-;; instruction for the shortest sequence, and 4 before the branch instruction
-;; if we have to jump around an unconditional branch.
-;; To the basic branch range the PC offset must be added (this is +4).
-;; So for forward branches we have
-;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
-;; And for backward branches we have
-;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
-;;
-;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
-;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
-
-(define_expand "cbranchsi4"
- [(set (pc) (if_then_else
- (match_operator 0 "arm_comparison_operator"
- [(match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "nonmemory_operand" "")])
- (label_ref (match_operand 3 "" ""))
- (pc)))]
- "TARGET_THUMB"
- "
- if (thumb_cmpneg_operand (operands[2], SImode))
- {
- emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
- operands[3], operands[0]));
- DONE;
- }
- if (!thumb_cmp_operand (operands[2], SImode))
- operands[2] = force_reg (SImode, operands[2]);
- ")
-
-(define_insn "*cbranchsi4_insn"
- [(set (pc) (if_then_else
- (match_operator 0 "arm_comparison_operator"
- [(match_operand:SI 1 "s_register_operand" "l,*h")
- (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
- (label_ref (match_operand 3 "" ""))
- (pc)))]
- "TARGET_THUMB"
- "*
- output_asm_insn (\"cmp\\t%1, %2\", operands);
-
- switch (get_attr_length (insn))
- {
- case 4: return \"b%d0\\t%l3\";
- case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
- default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
- }
- "
- [(set (attr "far_jump")
- (if_then_else
- (eq_attr "length" "8")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (and (ge (minus (match_dup 3) (pc)) (const_int -250))
- (le (minus (match_dup 3) (pc)) (const_int 256)))
- (const_int 4)
- (if_then_else
- (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
- (le (minus (match_dup 3) (pc)) (const_int 2048)))
- (const_int 6)
- (const_int 8))))]
-)
-
-(define_insn "cbranchsi4_scratch"
- [(set (pc) (if_then_else
- (match_operator 4 "arm_comparison_operator"
- [(match_operand:SI 1 "s_register_operand" "l,0")
- (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
- (label_ref (match_operand 3 "" ""))
- (pc)))
- (clobber (match_scratch:SI 0 "=l,l"))]
- "TARGET_THUMB"
- "*
- output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
-
- switch (get_attr_length (insn))
- {
- case 4: return \"b%d4\\t%l3\";
- case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
- default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
- }
- "
- [(set (attr "far_jump")
- (if_then_else
- (eq_attr "length" "8")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (and (ge (minus (match_dup 3) (pc)) (const_int -250))
- (le (minus (match_dup 3) (pc)) (const_int 256)))
- (const_int 4)
- (if_then_else
- (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
- (le (minus (match_dup 3) (pc)) (const_int 2048)))
- (const_int 6)
- (const_int 8))))]
-)
-(define_insn "*movsi_cbranchsi4"
- [(set (pc)
- (if_then_else
- (match_operator 3 "arm_comparison_operator"
- [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
- (const_int 0)])
- (label_ref (match_operand 2 "" ""))
- (pc)))
- (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
- (match_dup 1))]
- "TARGET_THUMB"
- "*{
- if (which_alternative == 0)
- output_asm_insn (\"cmp\t%0, #0\", operands);
- else if (which_alternative == 1)
- output_asm_insn (\"sub\t%0, %1, #0\", operands);
- else
- {
- output_asm_insn (\"cmp\t%1, #0\", operands);
- if (which_alternative == 2)
- output_asm_insn (\"mov\t%0, %1\", operands);
- else
- output_asm_insn (\"str\t%1, %0\", operands);
- }
- switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
- {
- case 4: return \"b%d3\\t%l2\";
- case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
- default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
- }
- }"
- [(set (attr "far_jump")
- (if_then_else
- (ior (and (gt (symbol_ref ("which_alternative"))
- (const_int 1))
- (eq_attr "length" "8"))
- (eq_attr "length" "10"))
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (le (symbol_ref ("which_alternative"))
- (const_int 1))
- (if_then_else
- (and (ge (minus (match_dup 2) (pc)) (const_int -250))
- (le (minus (match_dup 2) (pc)) (const_int 256)))
- (const_int 4)
- (if_then_else
- (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
- (le (minus (match_dup 2) (pc)) (const_int 2048)))
- (const_int 6)
- (const_int 8)))
- (if_then_else
- (and (ge (minus (match_dup 2) (pc)) (const_int -248))
- (le (minus (match_dup 2) (pc)) (const_int 256)))
- (const_int 6)
- (if_then_else
- (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
- (le (minus (match_dup 2) (pc)) (const_int 2048)))
- (const_int 8)
- (const_int 10)))))]
-)
-
-(define_insn "*negated_cbranchsi4"
- [(set (pc)
- (if_then_else
- (match_operator 0 "equality_operator"
- [(match_operand:SI 1 "s_register_operand" "l")
- (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
- (label_ref (match_operand 3 "" ""))
- (pc)))]
- "TARGET_THUMB"
- "*
- output_asm_insn (\"cmn\\t%1, %2\", operands);
- switch (get_attr_length (insn))
- {
- case 4: return \"b%d0\\t%l3\";
- case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
- default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
- }
- "
- [(set (attr "far_jump")
- (if_then_else
- (eq_attr "length" "8")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (and (ge (minus (match_dup 3) (pc)) (const_int -250))
- (le (minus (match_dup 3) (pc)) (const_int 256)))
- (const_int 4)
- (if_then_else
- (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
- (le (minus (match_dup 3) (pc)) (const_int 2048)))
- (const_int 6)
- (const_int 8))))]
-)
-
-(define_insn "*tbit_cbranch"
- [(set (pc)
- (if_then_else
- (match_operator 0 "equality_operator"
- [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
- (const_int 1)
- (match_operand:SI 2 "const_int_operand" "i"))
- (const_int 0)])
- (label_ref (match_operand 3 "" ""))
- (pc)))
- (clobber (match_scratch:SI 4 "=l"))]
- "TARGET_THUMB"
- "*
- {
- rtx op[3];
- op[0] = operands[4];
- op[1] = operands[1];
- op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
-
- output_asm_insn (\"lsl\\t%0, %1, %2\", op);
- switch (get_attr_length (insn))
- {
- case 4: return \"b%d0\\t%l3\";
- case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
- default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
- }
- }"
- [(set (attr "far_jump")
- (if_then_else
- (eq_attr "length" "8")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (and (ge (minus (match_dup 3) (pc)) (const_int -250))
- (le (minus (match_dup 3) (pc)) (const_int 256)))
- (const_int 4)
- (if_then_else
- (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
- (le (minus (match_dup 3) (pc)) (const_int 2048)))
- (const_int 6)
- (const_int 8))))]
-)
-
-(define_insn "*tlobits_cbranch"
- [(set (pc)
- (if_then_else
- (match_operator 0 "equality_operator"
- [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
- (match_operand:SI 2 "const_int_operand" "i")
- (const_int 0))
- (const_int 0)])
- (label_ref (match_operand 3 "" ""))
- (pc)))
- (clobber (match_scratch:SI 4 "=l"))]
- "TARGET_THUMB"
- "*
- {
- rtx op[3];
- op[0] = operands[4];
- op[1] = operands[1];
- op[2] = GEN_INT (32 - INTVAL (operands[2]));
-
- output_asm_insn (\"lsl\\t%0, %1, %2\", op);
- switch (get_attr_length (insn))
- {
- case 4: return \"b%d0\\t%l3\";
- case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
- default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
- }
- }"
- [(set (attr "far_jump")
- (if_then_else
- (eq_attr "length" "8")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (and (ge (minus (match_dup 3) (pc)) (const_int -250))
- (le (minus (match_dup 3) (pc)) (const_int 256)))
- (const_int 4)
- (if_then_else
- (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
- (le (minus (match_dup 3) (pc)) (const_int 2048)))
- (const_int 6)
- (const_int 8))))]
-)
-
-(define_insn "*tstsi3_cbranch"
- [(set (pc)
- (if_then_else
- (match_operator 3 "equality_operator"
- [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
- (match_operand:SI 1 "s_register_operand" "l"))
- (const_int 0)])
- (label_ref (match_operand 2 "" ""))
- (pc)))]
- "TARGET_THUMB"
- "*
- {
- output_asm_insn (\"tst\\t%0, %1\", operands);
- switch (get_attr_length (insn))
- {
- case 4: return \"b%d3\\t%l2\";
- case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
- default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
- }
- }"
- [(set (attr "far_jump")
- (if_then_else
- (eq_attr "length" "8")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (and (ge (minus (match_dup 2) (pc)) (const_int -250))
- (le (minus (match_dup 2) (pc)) (const_int 256)))
- (const_int 4)
- (if_then_else
- (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
- (le (minus (match_dup 2) (pc)) (const_int 2048)))
- (const_int 6)
- (const_int 8))))]
-)
-
-(define_insn "*andsi3_cbranch"
- [(set (pc)
- (if_then_else
- (match_operator 5 "equality_operator"
- [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
- (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
- (const_int 0)])
- (label_ref (match_operand 4 "" ""))
- (pc)))
- (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
- (and:SI (match_dup 2) (match_dup 3)))
- (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
- "TARGET_THUMB"
- "*
- {
- if (which_alternative == 0)
- output_asm_insn (\"and\\t%0, %3\", operands);
- else if (which_alternative == 1)
- {
- output_asm_insn (\"and\\t%1, %3\", operands);
- output_asm_insn (\"mov\\t%0, %1\", operands);
- }
- else
- {
- output_asm_insn (\"and\\t%1, %3\", operands);
- output_asm_insn (\"str\\t%1, %0\", operands);
- }
-
- switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
- {
- case 4: return \"b%d5\\t%l4\";
- case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
- default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
- }
- }"
- [(set (attr "far_jump")
- (if_then_else
- (ior (and (eq (symbol_ref ("which_alternative"))
- (const_int 0))
- (eq_attr "length" "8"))
- (eq_attr "length" "10"))
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (eq (symbol_ref ("which_alternative"))
- (const_int 0))
- (if_then_else
- (and (ge (minus (match_dup 4) (pc)) (const_int -250))
- (le (minus (match_dup 4) (pc)) (const_int 256)))
- (const_int 4)
- (if_then_else
- (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
- (le (minus (match_dup 4) (pc)) (const_int 2048)))
- (const_int 6)
- (const_int 8)))
- (if_then_else
- (and (ge (minus (match_dup 4) (pc)) (const_int -248))
- (le (minus (match_dup 4) (pc)) (const_int 256)))
- (const_int 6)
- (if_then_else
- (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
- (le (minus (match_dup 4) (pc)) (const_int 2048)))
- (const_int 8)
- (const_int 10)))))]
-)
-
-(define_insn "*orrsi3_cbranch_scratch"
- [(set (pc)
- (if_then_else
- (match_operator 4 "equality_operator"
- [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "s_register_operand" "l"))
- (const_int 0)])
- (label_ref (match_operand 3 "" ""))
- (pc)))
- (clobber (match_scratch:SI 0 "=l"))]
- "TARGET_THUMB"
- "*
- {
- output_asm_insn (\"orr\\t%0, %2\", operands);
- switch (get_attr_length (insn))
- {
- case 4: return \"b%d4\\t%l3\";
- case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
- default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
- }
- }"
- [(set (attr "far_jump")
- (if_then_else
- (eq_attr "length" "8")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (and (ge (minus (match_dup 3) (pc)) (const_int -250))
- (le (minus (match_dup 3) (pc)) (const_int 256)))
- (const_int 4)
- (if_then_else
- (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
- (le (minus (match_dup 3) (pc)) (const_int 2048)))
- (const_int 6)
- (const_int 8))))]
-)
-
-(define_insn "*orrsi3_cbranch"
- [(set (pc)
- (if_then_else
- (match_operator 5 "equality_operator"
- [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
- (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
- (const_int 0)])
- (label_ref (match_operand 4 "" ""))
- (pc)))
- (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
- (ior:SI (match_dup 2) (match_dup 3)))
- (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
- "TARGET_THUMB"
- "*
- {
- if (which_alternative == 0)
- output_asm_insn (\"orr\\t%0, %3\", operands);
- else if (which_alternative == 1)
- {
- output_asm_insn (\"orr\\t%1, %3\", operands);
- output_asm_insn (\"mov\\t%0, %1\", operands);
- }
- else
- {
- output_asm_insn (\"orr\\t%1, %3\", operands);
- output_asm_insn (\"str\\t%1, %0\", operands);
- }
-
- switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
- {
- case 4: return \"b%d5\\t%l4\";
- case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
- default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
- }
- }"
- [(set (attr "far_jump")
- (if_then_else
- (ior (and (eq (symbol_ref ("which_alternative"))
- (const_int 0))
- (eq_attr "length" "8"))
- (eq_attr "length" "10"))
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (eq (symbol_ref ("which_alternative"))
- (const_int 0))
- (if_then_else
- (and (ge (minus (match_dup 4) (pc)) (const_int -250))
- (le (minus (match_dup 4) (pc)) (const_int 256)))
- (const_int 4)
- (if_then_else
- (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
- (le (minus (match_dup 4) (pc)) (const_int 2048)))
- (const_int 6)
- (const_int 8)))
- (if_then_else
- (and (ge (minus (match_dup 4) (pc)) (const_int -248))
- (le (minus (match_dup 4) (pc)) (const_int 256)))
- (const_int 6)
- (if_then_else
- (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
- (le (minus (match_dup 4) (pc)) (const_int 2048)))
- (const_int 8)
- (const_int 10)))))]
-)
-
-(define_insn "*xorsi3_cbranch_scratch"
- [(set (pc)
- (if_then_else
- (match_operator 4 "equality_operator"
- [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "s_register_operand" "l"))
- (const_int 0)])
- (label_ref (match_operand 3 "" ""))
- (pc)))
- (clobber (match_scratch:SI 0 "=l"))]
- "TARGET_THUMB"
- "*
- {
- output_asm_insn (\"eor\\t%0, %2\", operands);
- switch (get_attr_length (insn))
- {
- case 4: return \"b%d4\\t%l3\";
- case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
- default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
- }
- }"
- [(set (attr "far_jump")
- (if_then_else
- (eq_attr "length" "8")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (and (ge (minus (match_dup 3) (pc)) (const_int -250))
- (le (minus (match_dup 3) (pc)) (const_int 256)))
- (const_int 4)
- (if_then_else
- (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
- (le (minus (match_dup 3) (pc)) (const_int 2048)))
- (const_int 6)
- (const_int 8))))]
-)
-
-(define_insn "*xorsi3_cbranch"
- [(set (pc)
- (if_then_else
- (match_operator 5 "equality_operator"
- [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
- (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
- (const_int 0)])
- (label_ref (match_operand 4 "" ""))
- (pc)))
- (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
- (xor:SI (match_dup 2) (match_dup 3)))
- (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
- "TARGET_THUMB"
- "*
- {
- if (which_alternative == 0)
- output_asm_insn (\"eor\\t%0, %3\", operands);
- else if (which_alternative == 1)
- {
- output_asm_insn (\"eor\\t%1, %3\", operands);
- output_asm_insn (\"mov\\t%0, %1\", operands);
- }
- else
- {
- output_asm_insn (\"eor\\t%1, %3\", operands);
- output_asm_insn (\"str\\t%1, %0\", operands);
- }
-
- switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
- {
- case 4: return \"b%d5\\t%l4\";
- case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
- default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
- }
- }"
- [(set (attr "far_jump")
- (if_then_else
- (ior (and (eq (symbol_ref ("which_alternative"))
- (const_int 0))
- (eq_attr "length" "8"))
- (eq_attr "length" "10"))
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (eq (symbol_ref ("which_alternative"))
- (const_int 0))
- (if_then_else
- (and (ge (minus (match_dup 4) (pc)) (const_int -250))
- (le (minus (match_dup 4) (pc)) (const_int 256)))
- (const_int 4)
- (if_then_else
- (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
- (le (minus (match_dup 4) (pc)) (const_int 2048)))
- (const_int 6)
- (const_int 8)))
- (if_then_else
- (and (ge (minus (match_dup 4) (pc)) (const_int -248))
- (le (minus (match_dup 4) (pc)) (const_int 256)))
- (const_int 6)
- (if_then_else
- (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
- (le (minus (match_dup 4) (pc)) (const_int 2048)))
- (const_int 8)
- (const_int 10)))))]
-)
-
-(define_insn "*bicsi3_cbranch_scratch"
- [(set (pc)
- (if_then_else
- (match_operator 4 "equality_operator"
- [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
- (match_operand:SI 1 "s_register_operand" "0"))
- (const_int 0)])
- (label_ref (match_operand 3 "" ""))
- (pc)))
- (clobber (match_scratch:SI 0 "=l"))]
- "TARGET_THUMB"
- "*
- {
- output_asm_insn (\"bic\\t%0, %2\", operands);
- switch (get_attr_length (insn))
- {
- case 4: return \"b%d4\\t%l3\";
- case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
- default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
- }
- }"
- [(set (attr "far_jump")
- (if_then_else
- (eq_attr "length" "8")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (and (ge (minus (match_dup 3) (pc)) (const_int -250))
- (le (minus (match_dup 3) (pc)) (const_int 256)))
- (const_int 4)
- (if_then_else
- (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
- (le (minus (match_dup 3) (pc)) (const_int 2048)))
- (const_int 6)
- (const_int 8))))]
-)
-
-(define_insn "*bicsi3_cbranch"
- [(set (pc)
- (if_then_else
- (match_operator 5 "equality_operator"
- [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
- (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
- (const_int 0)])
- (label_ref (match_operand 4 "" ""))
- (pc)))
- (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
- (and:SI (not:SI (match_dup 3)) (match_dup 2)))
- (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
- "TARGET_THUMB"
- "*
- {
- if (which_alternative == 0)
- output_asm_insn (\"bic\\t%0, %3\", operands);
- else if (which_alternative <= 2)
- {
- output_asm_insn (\"bic\\t%1, %3\", operands);
- /* It's ok if OP0 is a lo-reg, even though the mov will set the
- conditions again, since we're only testing for equality. */
- output_asm_insn (\"mov\\t%0, %1\", operands);
- }
- else
- {
- output_asm_insn (\"bic\\t%1, %3\", operands);
- output_asm_insn (\"str\\t%1, %0\", operands);
- }
-
- switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
- {
- case 4: return \"b%d5\\t%l4\";
- case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
- default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
- }
- }"
- [(set (attr "far_jump")
- (if_then_else
- (ior (and (eq (symbol_ref ("which_alternative"))
- (const_int 0))
- (eq_attr "length" "8"))
- (eq_attr "length" "10"))
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (eq (symbol_ref ("which_alternative"))
- (const_int 0))
- (if_then_else
- (and (ge (minus (match_dup 4) (pc)) (const_int -250))
- (le (minus (match_dup 4) (pc)) (const_int 256)))
- (const_int 4)
- (if_then_else
- (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
- (le (minus (match_dup 4) (pc)) (const_int 2048)))
- (const_int 6)
- (const_int 8)))
- (if_then_else
- (and (ge (minus (match_dup 4) (pc)) (const_int -248))
- (le (minus (match_dup 4) (pc)) (const_int 256)))
- (const_int 6)
- (if_then_else
- (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
- (le (minus (match_dup 4) (pc)) (const_int 2048)))
- (const_int 8)
- (const_int 10)))))]
-)
-
-(define_insn "*cbranchne_decr1"
- [(set (pc)
- (if_then_else (match_operator 3 "equality_operator"
- [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
- (const_int 0)])
- (label_ref (match_operand 4 "" ""))
- (pc)))
- (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
- (plus:SI (match_dup 2) (const_int -1)))
- (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
- "TARGET_THUMB"
- "*
- {
- rtx cond[2];
- cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
- ? GEU : LTU),
- VOIDmode, operands[2], const1_rtx);
- cond[1] = operands[4];
-
- if (which_alternative == 0)
- output_asm_insn (\"sub\\t%0, %2, #1\", operands);
- else if (which_alternative == 1)
- {
- /* We must provide an alternative for a hi reg because reload
- cannot handle output reloads on a jump instruction, but we
- can't subtract into that. Fortunately a mov from lo to hi
- does not clobber the condition codes. */
- output_asm_insn (\"sub\\t%1, %2, #1\", operands);
- output_asm_insn (\"mov\\t%0, %1\", operands);
- }
- else
- {
- /* Similarly, but the target is memory. */
- output_asm_insn (\"sub\\t%1, %2, #1\", operands);
- output_asm_insn (\"str\\t%1, %0\", operands);
- }
-
- switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
- {
- case 4:
- output_asm_insn (\"b%d0\\t%l1\", cond);
- return \"\";
- case 6:
- output_asm_insn (\"b%D0\\t.LCB%=\", cond);
- return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
- default:
- output_asm_insn (\"b%D0\\t.LCB%=\", cond);
- return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
- }
- }
- "
- [(set (attr "far_jump")
- (if_then_else
- (ior (and (eq (symbol_ref ("which_alternative"))
- (const_int 0))
- (eq_attr "length" "8"))
- (eq_attr "length" "10"))
- (const_string "yes")
- (const_string "no")))
- (set_attr_alternative "length"
- [
- ;; Alternative 0
- (if_then_else
- (and (ge (minus (match_dup 4) (pc)) (const_int -250))
- (le (minus (match_dup 4) (pc)) (const_int 256)))
- (const_int 4)
- (if_then_else
- (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
- (le (minus (match_dup 4) (pc)) (const_int 2048)))
- (const_int 6)
- (const_int 8)))
- ;; Alternative 1
- (if_then_else
- (and (ge (minus (match_dup 4) (pc)) (const_int -248))
- (le (minus (match_dup 4) (pc)) (const_int 256)))
- (const_int 6)
- (if_then_else
- (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
- (le (minus (match_dup 4) (pc)) (const_int 2048)))
- (const_int 8)
- (const_int 10)))
- ;; Alternative 2
- (if_then_else
- (and (ge (minus (match_dup 4) (pc)) (const_int -248))
- (le (minus (match_dup 4) (pc)) (const_int 256)))
- (const_int 6)
- (if_then_else
- (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
- (le (minus (match_dup 4) (pc)) (const_int 2048)))
- (const_int 8)
- (const_int 10)))
- ;; Alternative 3
- (if_then_else
- (and (ge (minus (match_dup 4) (pc)) (const_int -248))
- (le (minus (match_dup 4) (pc)) (const_int 256)))
- (const_int 6)
- (if_then_else
- (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
- (le (minus (match_dup 4) (pc)) (const_int 2048)))
- (const_int 8)
- (const_int 10)))])]
-)
-
-(define_insn "*addsi3_cbranch"
- [(set (pc)
- (if_then_else
- (match_operator 4 "comparison_operator"
- [(plus:SI
- (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
- (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
- (const_int 0)])
- (label_ref (match_operand 5 "" ""))
- (pc)))
- (set
- (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
- (plus:SI (match_dup 2) (match_dup 3)))
- (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
- "TARGET_THUMB
- && (GET_CODE (operands[4]) == EQ
- || GET_CODE (operands[4]) == NE
- || GET_CODE (operands[4]) == GE
- || GET_CODE (operands[4]) == LT)"
- "*
- {
- rtx cond[3];
-
-
- cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
- cond[1] = operands[2];
- cond[2] = operands[3];
-
- if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
- output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
- else
- output_asm_insn (\"add\\t%0, %1, %2\", cond);
-
- if (which_alternative >= 3
- && which_alternative < 4)
- output_asm_insn (\"mov\\t%0, %1\", operands);
- else if (which_alternative >= 4)
- output_asm_insn (\"str\\t%1, %0\", operands);
-
- switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
- {
- case 4:
- return \"b%d4\\t%l5\";
- case 6:
- return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
- default:
- return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
- }
- }
- "
- [(set (attr "far_jump")
- (if_then_else
- (ior (and (lt (symbol_ref ("which_alternative"))
- (const_int 3))
- (eq_attr "length" "8"))
- (eq_attr "length" "10"))
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (lt (symbol_ref ("which_alternative"))
- (const_int 3))
- (if_then_else
- (and (ge (minus (match_dup 5) (pc)) (const_int -250))
- (le (minus (match_dup 5) (pc)) (const_int 256)))
- (const_int 4)
- (if_then_else
- (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
- (le (minus (match_dup 5) (pc)) (const_int 2048)))
- (const_int 6)
- (const_int 8)))
- (if_then_else
- (and (ge (minus (match_dup 5) (pc)) (const_int -248))
- (le (minus (match_dup 5) (pc)) (const_int 256)))
- (const_int 6)
- (if_then_else
- (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
- (le (minus (match_dup 5) (pc)) (const_int 2048)))
- (const_int 8)
- (const_int 10)))))]
-)
-
-(define_insn "*addsi3_cbranch_scratch"
- [(set (pc)
- (if_then_else
- (match_operator 3 "comparison_operator"
- [(plus:SI
- (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
- (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
- (const_int 0)])
- (label_ref (match_operand 4 "" ""))
- (pc)))
- (clobber (match_scratch:SI 0 "=X,X,l,l"))]
- "TARGET_THUMB
- && (GET_CODE (operands[3]) == EQ
- || GET_CODE (operands[3]) == NE
- || GET_CODE (operands[3]) == GE
- || GET_CODE (operands[3]) == LT)"
- "*
- {
- switch (which_alternative)
- {
- case 0:
- output_asm_insn (\"cmp\t%1, #%n2\", operands);
- break;
- case 1:
- output_asm_insn (\"cmn\t%1, %2\", operands);
- break;
- case 2:
- if (INTVAL (operands[2]) < 0)
- output_asm_insn (\"sub\t%0, %1, %2\", operands);
- else
- output_asm_insn (\"add\t%0, %1, %2\", operands);
- break;
- case 3:
- if (INTVAL (operands[2]) < 0)
- output_asm_insn (\"sub\t%0, %0, %2\", operands);
- else
- output_asm_insn (\"add\t%0, %0, %2\", operands);
- break;
- }
-
- switch (get_attr_length (insn))
- {
- case 4:
- return \"b%d3\\t%l4\";
- case 6:
- return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
- default:
- return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
- }
- }
- "
- [(set (attr "far_jump")
- (if_then_else
- (eq_attr "length" "8")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (and (ge (minus (match_dup 4) (pc)) (const_int -250))
- (le (minus (match_dup 4) (pc)) (const_int 256)))
- (const_int 4)
- (if_then_else
- (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
- (le (minus (match_dup 4) (pc)) (const_int 2048)))
- (const_int 6)
- (const_int 8))))]
-)
-
-(define_insn "*subsi3_cbranch"
- [(set (pc)
- (if_then_else
- (match_operator 4 "comparison_operator"
- [(minus:SI
- (match_operand:SI 2 "s_register_operand" "l,l,1,l")
- (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
- (const_int 0)])
- (label_ref (match_operand 5 "" ""))
- (pc)))
- (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
- (minus:SI (match_dup 2) (match_dup 3)))
- (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
- "TARGET_THUMB
- && (GET_CODE (operands[4]) == EQ
- || GET_CODE (operands[4]) == NE
- || GET_CODE (operands[4]) == GE
- || GET_CODE (operands[4]) == LT)"
- "*
- {
- if (which_alternative == 0)
- output_asm_insn (\"sub\\t%0, %2, %3\", operands);
- else if (which_alternative == 1)
- {
- /* We must provide an alternative for a hi reg because reload
- cannot handle output reloads on a jump instruction, but we
- can't subtract into that. Fortunately a mov from lo to hi
- does not clobber the condition codes. */
- output_asm_insn (\"sub\\t%1, %2, %3\", operands);
- output_asm_insn (\"mov\\t%0, %1\", operands);
- }
- else
- {
- /* Similarly, but the target is memory. */
- output_asm_insn (\"sub\\t%1, %2, %3\", operands);
- output_asm_insn (\"str\\t%1, %0\", operands);
- }
-
- switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
- {
- case 4:
- return \"b%d4\\t%l5\";
- case 6:
- return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
- default:
- return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
- }
- }
- "
- [(set (attr "far_jump")
- (if_then_else
- (ior (and (eq (symbol_ref ("which_alternative"))
- (const_int 0))
- (eq_attr "length" "8"))
- (eq_attr "length" "10"))
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (eq (symbol_ref ("which_alternative"))
- (const_int 0))
- (if_then_else
- (and (ge (minus (match_dup 5) (pc)) (const_int -250))
- (le (minus (match_dup 5) (pc)) (const_int 256)))
- (const_int 4)
- (if_then_else
- (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
- (le (minus (match_dup 5) (pc)) (const_int 2048)))
- (const_int 6)
- (const_int 8)))
- (if_then_else
- (and (ge (minus (match_dup 5) (pc)) (const_int -248))
- (le (minus (match_dup 5) (pc)) (const_int 256)))
- (const_int 6)
- (if_then_else
- (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
- (le (minus (match_dup 5) (pc)) (const_int 2048)))
- (const_int 8)
- (const_int 10)))))]
-)
-
-(define_insn "*subsi3_cbranch_scratch"
- [(set (pc)
- (if_then_else
- (match_operator 0 "arm_comparison_operator"
- [(minus:SI (match_operand:SI 1 "register_operand" "l")
- (match_operand:SI 2 "nonmemory_operand" "l"))
- (const_int 0)])
- (label_ref (match_operand 3 "" ""))
- (pc)))]
- "TARGET_THUMB
- && (GET_CODE (operands[0]) == EQ
- || GET_CODE (operands[0]) == NE
- || GET_CODE (operands[0]) == GE
- || GET_CODE (operands[0]) == LT)"
- "*
- output_asm_insn (\"cmp\\t%1, %2\", operands);
- switch (get_attr_length (insn))
- {
- case 4: return \"b%d0\\t%l3\";
- case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
- default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
- }
- "
- [(set (attr "far_jump")
- (if_then_else
- (eq_attr "length" "8")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (and (ge (minus (match_dup 3) (pc)) (const_int -250))
- (le (minus (match_dup 3) (pc)) (const_int 256)))
- (const_int 4)
- (if_then_else
- (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
- (le (minus (match_dup 3) (pc)) (const_int 2048)))
- (const_int 6)
- (const_int 8))))]
-)
-
-;; Comparison and test insns
-
-(define_expand "cmpsi"
- [(match_operand:SI 0 "s_register_operand" "")
- (match_operand:SI 1 "arm_add_operand" "")]
- "TARGET_ARM"
- "{
- arm_compare_op0 = operands[0];
- arm_compare_op1 = operands[1];
- DONE;
- }"
-)
-
-(define_expand "cmpsf"
- [(match_operand:SF 0 "s_register_operand" "")
- (match_operand:SF 1 "arm_float_compare_operand" "")]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "
- arm_compare_op0 = operands[0];
- arm_compare_op1 = operands[1];
- DONE;
- "
-)
-
-(define_expand "cmpdf"
- [(match_operand:DF 0 "s_register_operand" "")
- (match_operand:DF 1 "arm_float_compare_operand" "")]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "
- arm_compare_op0 = operands[0];
- arm_compare_op1 = operands[1];
- DONE;
- "
-)
-
-(define_insn "*arm_cmpsi_insn"
- [(set (reg:CC CC_REGNUM)
- (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
- (match_operand:SI 1 "arm_add_operand" "rI,L")))]
- "TARGET_ARM"
- "@
- cmp%?\\t%0, %1
- cmn%?\\t%0, #%n1"
- [(set_attr "conds" "set")]
-)
-
-(define_insn "*cmpsi_shiftsi"
- [(set (reg:CC CC_REGNUM)
- (compare:CC (match_operand:SI 0 "s_register_operand" "r")
- (match_operator:SI 3 "shift_operator"
- [(match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
- "TARGET_ARM"
- "cmp%?\\t%0, %1%S3"
- [(set_attr "conds" "set")
- (set_attr "shift" "1")
- (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
- (const_string "alu_shift")
- (const_string "alu_shift_reg")))]
-)
-
-(define_insn "*cmpsi_shiftsi_swp"
- [(set (reg:CC_SWP CC_REGNUM)
- (compare:CC_SWP (match_operator:SI 3 "shift_operator"
- [(match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "reg_or_int_operand" "rM")])
- (match_operand:SI 0 "s_register_operand" "r")))]
- "TARGET_ARM"
- "cmp%?\\t%0, %1%S3"
- [(set_attr "conds" "set")
- (set_attr "shift" "1")
- (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
- (const_string "alu_shift")
- (const_string "alu_shift_reg")))]
-)
-
-(define_insn "*cmpsi_negshiftsi_si"
- [(set (reg:CC_Z CC_REGNUM)
- (compare:CC_Z
- (neg:SI (match_operator:SI 1 "shift_operator"
- [(match_operand:SI 2 "s_register_operand" "r")
- (match_operand:SI 3 "reg_or_int_operand" "rM")]))
- (match_operand:SI 0 "s_register_operand" "r")))]
- "TARGET_ARM"
- "cmn%?\\t%0, %2%S1"
- [(set_attr "conds" "set")
- (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
- (const_string "alu_shift")
- (const_string "alu_shift_reg")))]
-)
-
-;; Cirrus SF compare instruction
-(define_insn "*cirrus_cmpsf"
- [(set (reg:CCFP CC_REGNUM)
- (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
- (match_operand:SF 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cfcmps%?\\tr15, %V0, %V1"
- [(set_attr "type" "mav_farith")
- (set_attr "cirrus" "compare")]
-)
-
-;; Cirrus DF compare instruction
-(define_insn "*cirrus_cmpdf"
- [(set (reg:CCFP CC_REGNUM)
- (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
- (match_operand:DF 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cfcmpd%?\\tr15, %V0, %V1"
- [(set_attr "type" "mav_farith")
- (set_attr "cirrus" "compare")]
-)
-
-;; Cirrus DI compare instruction
-(define_expand "cmpdi"
- [(match_operand:DI 0 "cirrus_fp_register" "")
- (match_operand:DI 1 "cirrus_fp_register" "")]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "{
- arm_compare_op0 = operands[0];
- arm_compare_op1 = operands[1];
- DONE;
- }")
-
-(define_insn "*cirrus_cmpdi"
- [(set (reg:CC CC_REGNUM)
- (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
- (match_operand:DI 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cfcmp64%?\\tr15, %V0, %V1"
- [(set_attr "type" "mav_farith")
- (set_attr "cirrus" "compare")]
-)
-
-; This insn allows redundant compares to be removed by cse, nothing should
-; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
-; is deleted later on. The match_dup will match the mode here, so that
-; mode changes of the condition codes aren't lost by this even though we don't
-; specify what they are.
-
-(define_insn "*deleted_compare"
- [(set (match_operand 0 "cc_register" "") (match_dup 0))]
- "TARGET_ARM"
- "\\t%@ deleted compare"
- [(set_attr "conds" "set")
- (set_attr "length" "0")]
-)
-
-
-;; Conditional branch insns
-
-(define_expand "beq"
- [(set (pc)
- (if_then_else (eq (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_ARM"
- "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "bne"
- [(set (pc)
- (if_then_else (ne (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_ARM"
- "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "bgt"
- [(set (pc)
- (if_then_else (gt (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_ARM"
- "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "ble"
- [(set (pc)
- (if_then_else (le (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_ARM"
- "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "bge"
- [(set (pc)
- (if_then_else (ge (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_ARM"
- "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "blt"
- [(set (pc)
- (if_then_else (lt (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_ARM"
- "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "bgtu"
- [(set (pc)
- (if_then_else (gtu (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_ARM"
- "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "bleu"
- [(set (pc)
- (if_then_else (leu (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_ARM"
- "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "bgeu"
- [(set (pc)
- (if_then_else (geu (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_ARM"
- "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "bltu"
- [(set (pc)
- (if_then_else (ltu (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_ARM"
- "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "bunordered"
- [(set (pc)
- (if_then_else (unordered (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
- arm_compare_op1);"
-)
-
-(define_expand "bordered"
- [(set (pc)
- (if_then_else (ordered (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
- arm_compare_op1);"
-)
-
-(define_expand "bungt"
- [(set (pc)
- (if_then_else (ungt (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "bunlt"
- [(set (pc)
- (if_then_else (unlt (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "bunge"
- [(set (pc)
- (if_then_else (unge (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "bunle"
- [(set (pc)
- (if_then_else (unle (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
-)
-
-;; The following two patterns need two branch instructions, since there is
-;; no single instruction that will handle all cases.
-(define_expand "buneq"
- [(set (pc)
- (if_then_else (uneq (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "bltgt"
- [(set (pc)
- (if_then_else (ltgt (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
-)
-
-;;
-;; Patterns to match conditional branch insns.
-;;
-
-; Special pattern to match UNEQ.
-(define_insn "*arm_buneq"
- [(set (pc)
- (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "*
- gcc_assert (!arm_ccfsm_state);
-
- return \"bvs\\t%l0\;beq\\t%l0\";
- "
- [(set_attr "conds" "jump_clob")
- (set_attr "length" "8")]
-)
-
-; Special pattern to match LTGT.
-(define_insn "*arm_bltgt"
- [(set (pc)
- (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "*
- gcc_assert (!arm_ccfsm_state);
-
- return \"bmi\\t%l0\;bgt\\t%l0\";
- "
- [(set_attr "conds" "jump_clob")
- (set_attr "length" "8")]
-)
-
-(define_insn "*arm_cond_branch"
- [(set (pc)
- (if_then_else (match_operator 1 "arm_comparison_operator"
- [(match_operand 2 "cc_register" "") (const_int 0)])
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_ARM"
- "*
- if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
- {
- arm_ccfsm_state += 2;
- return \"\";
- }
- return \"b%d1\\t%l0\";
- "
- [(set_attr "conds" "use")
- (set_attr "type" "branch")]
-)
-
-; Special pattern to match reversed UNEQ.
-(define_insn "*arm_buneq_reversed"
- [(set (pc)
- (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "*
- gcc_assert (!arm_ccfsm_state);
-
- return \"bmi\\t%l0\;bgt\\t%l0\";
- "
- [(set_attr "conds" "jump_clob")
- (set_attr "length" "8")]
-)
-
-; Special pattern to match reversed LTGT.
-(define_insn "*arm_bltgt_reversed"
- [(set (pc)
- (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "*
- gcc_assert (!arm_ccfsm_state);
-
- return \"bvs\\t%l0\;beq\\t%l0\";
- "
- [(set_attr "conds" "jump_clob")
- (set_attr "length" "8")]
-)
-
-(define_insn "*arm_cond_branch_reversed"
- [(set (pc)
- (if_then_else (match_operator 1 "arm_comparison_operator"
- [(match_operand 2 "cc_register" "") (const_int 0)])
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_ARM"
- "*
- if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
- {
- arm_ccfsm_state += 2;
- return \"\";
- }
- return \"b%D1\\t%l0\";
- "
- [(set_attr "conds" "use")
- (set_attr "type" "branch")]
-)
-
-
-
-; scc insns
-
-(define_expand "seq"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (eq:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM"
- "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "sne"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (ne:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM"
- "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "sgt"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (gt:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM"
- "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "sle"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (le:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM"
- "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "sge"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (ge:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM"
- "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "slt"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (lt:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM"
- "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "sgtu"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (gtu:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM"
- "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "sleu"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (leu:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM"
- "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "sgeu"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (geu:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM"
- "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "sltu"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (ltu:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM"
- "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "sunordered"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (unordered:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
- arm_compare_op1);"
-)
-
-(define_expand "sordered"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (ordered:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
- arm_compare_op1);"
-)
-
-(define_expand "sungt"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (ungt:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
- arm_compare_op1);"
-)
-
-(define_expand "sunge"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (unge:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
- arm_compare_op1);"
-)
-
-(define_expand "sunlt"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (unlt:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
- arm_compare_op1);"
-)
-
-(define_expand "sunle"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (unle:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
- arm_compare_op1);"
-)
-
-;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
-;;; simple ARM instructions.
-;
-; (define_expand "suneq"
-; [(set (match_operand:SI 0 "s_register_operand" "")
-; (uneq:SI (match_dup 1) (const_int 0)))]
-; "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
-; "gcc_unreachable ();"
-; )
-;
-; (define_expand "sltgt"
-; [(set (match_operand:SI 0 "s_register_operand" "")
-; (ltgt:SI (match_dup 1) (const_int 0)))]
-; "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
-; "gcc_unreachable ();"
-; )
-
-(define_insn "*mov_scc"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (match_operator:SI 1 "arm_comparison_operator"
- [(match_operand 2 "cc_register" "") (const_int 0)]))]
- "TARGET_ARM"
- "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
- [(set_attr "conds" "use")
- (set_attr "length" "8")]
-)
-
-(define_insn "*mov_negscc"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (neg:SI (match_operator:SI 1 "arm_comparison_operator"
- [(match_operand 2 "cc_register" "") (const_int 0)])))]
- "TARGET_ARM"
- "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
- [(set_attr "conds" "use")
- (set_attr "length" "8")]
-)
-
-(define_insn "*mov_notscc"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (not:SI (match_operator:SI 1 "arm_comparison_operator"
- [(match_operand 2 "cc_register" "") (const_int 0)])))]
- "TARGET_ARM"
- "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
- [(set_attr "conds" "use")
- (set_attr "length" "8")]
-)
-
-
-;; Conditional move insns
-
-(define_expand "movsicc"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
- (match_operand:SI 2 "arm_not_operand" "")
- (match_operand:SI 3 "arm_not_operand" "")))]
- "TARGET_ARM"
- "
- {
- enum rtx_code code = GET_CODE (operands[1]);
- rtx ccreg;
-
- if (code == UNEQ || code == LTGT)
- FAIL;
-
- ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
- operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
- }"
-)
-
-(define_expand "movsfcc"
- [(set (match_operand:SF 0 "s_register_operand" "")
- (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
- (match_operand:SF 2 "s_register_operand" "")
- (match_operand:SF 3 "nonmemory_operand" "")))]
- "TARGET_ARM"
- "
- {
- enum rtx_code code = GET_CODE (operands[1]);
- rtx ccreg;
-
- if (code == UNEQ || code == LTGT)
- FAIL;
-
- /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
- Otherwise, ensure it is a valid FP add operand */
- if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
- || (!arm_float_add_operand (operands[3], SFmode)))
- operands[3] = force_reg (SFmode, operands[3]);
-
- ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
- operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
- }"
-)
-
-(define_expand "movdfcc"
- [(set (match_operand:DF 0 "s_register_operand" "")
- (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
- (match_operand:DF 2 "s_register_operand" "")
- (match_operand:DF 3 "arm_float_add_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "
- {
- enum rtx_code code = GET_CODE (operands[1]);
- rtx ccreg;
-
- if (code == UNEQ || code == LTGT)
- FAIL;
-
- ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
- operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
- }"
-)
-
-(define_insn "*movsicc_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
- (if_then_else:SI
- (match_operator 3 "arm_comparison_operator"
- [(match_operand 4 "cc_register" "") (const_int 0)])
- (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
- (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
- "TARGET_ARM"
- "@
- mov%D3\\t%0, %2
- mvn%D3\\t%0, #%B2
- mov%d3\\t%0, %1
- mvn%d3\\t%0, #%B1
- mov%d3\\t%0, %1\;mov%D3\\t%0, %2
- mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
- mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
- mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
- [(set_attr "length" "4,4,4,4,8,8,8,8")
- (set_attr "conds" "use")]
-)
-
-(define_insn "*movsfcc_soft_insn"
- [(set (match_operand:SF 0 "s_register_operand" "=r,r")
- (if_then_else:SF (match_operator 3 "arm_comparison_operator"
- [(match_operand 4 "cc_register" "") (const_int 0)])
- (match_operand:SF 1 "s_register_operand" "0,r")
- (match_operand:SF 2 "s_register_operand" "r,0")))]
- "TARGET_ARM && TARGET_SOFT_FLOAT"
- "@
- mov%D3\\t%0, %2
- mov%d3\\t%0, %1"
- [(set_attr "conds" "use")]
-)
-
-
-;; Jump and linkage insns
-
-(define_expand "jump"
- [(set (pc)
- (label_ref (match_operand 0 "" "")))]
- "TARGET_EITHER"
- ""
-)
-
-(define_insn "*arm_jump"
- [(set (pc)
- (label_ref (match_operand 0 "" "")))]
- "TARGET_ARM"
- "*
- {
- if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
- {
- arm_ccfsm_state += 2;
- return \"\";
- }
- return \"b%?\\t%l0\";
- }
- "
- [(set_attr "predicable" "yes")]
-)
-
-(define_insn "*thumb_jump"
- [(set (pc)
- (label_ref (match_operand 0 "" "")))]
- "TARGET_THUMB"
- "*
- 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 -2044))
- (le (minus (match_dup 0) (pc)) (const_int 2048)))
- (const_int 2)
- (const_int 4)))]
-)
-
-(define_expand "call"
- [(parallel [(call (match_operand 0 "memory_operand" "")
- (match_operand 1 "general_operand" ""))
- (use (match_operand 2 "" ""))
- (clobber (reg:SI LR_REGNUM))])]
- "TARGET_EITHER"
- "
- {
- rtx callee;
-
- /* In an untyped call, we can get NULL for operand 2. */
- if (operands[2] == NULL_RTX)
- operands[2] = const0_rtx;
-
- /* This is to decide if we should generate indirect calls by loading the
- 32 bit address of the callee into a register before performing the
- branch and link. operand[2] encodes the long_call/short_call
- attribute of the function being called. This attribute is set whenever
- __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
- is used, and the short_call attribute can also be set if function is
- declared as static or if it has already been defined in the current
- compilation unit. See arm.c and arm.h for info about this. The third
- parameter to arm_is_longcall_p is used to tell it which pattern
- invoked it. */
- callee = XEXP (operands[0], 0);
-
- if ((GET_CODE (callee) == SYMBOL_REF
- && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
- || (GET_CODE (callee) != SYMBOL_REF
- && GET_CODE (callee) != REG))
- XEXP (operands[0], 0) = force_reg (Pmode, callee);
- }"
-)
-
-(define_insn "*call_reg_armv5"
- [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
- (match_operand 1 "" ""))
- (use (match_operand 2 "" ""))
- (clobber (reg:SI LR_REGNUM))]
- "TARGET_ARM && arm_arch5"
- "blx%?\\t%0"
- [(set_attr "type" "call")]
-)
-
-(define_insn "*call_reg_arm"
- [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
- (match_operand 1 "" ""))
- (use (match_operand 2 "" ""))
- (clobber (reg:SI LR_REGNUM))]
- "TARGET_ARM && !arm_arch5"
- "*
- return output_call (operands);
- "
- ;; length is worst case, normally it is only two
- [(set_attr "length" "12")
- (set_attr "type" "call")]
-)
-
-(define_insn "*call_mem"
- [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
- (match_operand 1 "" ""))
- (use (match_operand 2 "" ""))
- (clobber (reg:SI LR_REGNUM))]
- "TARGET_ARM"
- "*
- return output_call_mem (operands);
- "
- [(set_attr "length" "12")
- (set_attr "type" "call")]
-)
-
-(define_insn "*call_reg_thumb_v5"
- [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
- (match_operand 1 "" ""))
- (use (match_operand 2 "" ""))
- (clobber (reg:SI LR_REGNUM))]
- "TARGET_THUMB && arm_arch5"
- "blx\\t%0"
- [(set_attr "length" "2")
- (set_attr "type" "call")]
-)
-
-(define_insn "*call_reg_thumb"
- [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
- (match_operand 1 "" ""))
- (use (match_operand 2 "" ""))
- (clobber (reg:SI LR_REGNUM))]
- "TARGET_THUMB && !arm_arch5"
- "*
- {
- if (!TARGET_CALLER_INTERWORKING)
- return thumb_call_via_reg (operands[0]);
- else if (operands[1] == const0_rtx)
- return \"bl\\t%__interwork_call_via_%0\";
- else if (frame_pointer_needed)
- return \"bl\\t%__interwork_r7_call_via_%0\";
- else
- return \"bl\\t%__interwork_r11_call_via_%0\";
- }"
- [(set_attr "type" "call")]
-)
-
-(define_expand "call_value"
- [(parallel [(set (match_operand 0 "" "")
- (call (match_operand 1 "memory_operand" "")
- (match_operand 2 "general_operand" "")))
- (use (match_operand 3 "" ""))
- (clobber (reg:SI LR_REGNUM))])]
- "TARGET_EITHER"
- "
- {
- rtx callee = XEXP (operands[1], 0);
-
- /* In an untyped call, we can get NULL for operand 2. */
- if (operands[3] == 0)
- operands[3] = const0_rtx;
-
- /* See the comment in define_expand \"call\". */
- if ((GET_CODE (callee) == SYMBOL_REF
- && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
- || (GET_CODE (callee) != SYMBOL_REF
- && GET_CODE (callee) != REG))
- XEXP (operands[1], 0) = force_reg (Pmode, callee);
- }"
-)
-
-(define_insn "*call_value_reg_armv5"
- [(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
- (match_operand 2 "" "")))
- (use (match_operand 3 "" ""))
- (clobber (reg:SI LR_REGNUM))]
- "TARGET_ARM && arm_arch5"
- "blx%?\\t%1"
- [(set_attr "type" "call")]
-)
-
-(define_insn "*call_value_reg_arm"
- [(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
- (match_operand 2 "" "")))
- (use (match_operand 3 "" ""))
- (clobber (reg:SI LR_REGNUM))]
- "TARGET_ARM && !arm_arch5"
- "*
- return output_call (&operands[1]);
- "
- [(set_attr "length" "12")
- (set_attr "type" "call")]
-)
-
-(define_insn "*call_value_mem"
- [(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
- (match_operand 2 "" "")))
- (use (match_operand 3 "" ""))
- (clobber (reg:SI LR_REGNUM))]
- "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
- "*
- return output_call_mem (&operands[1]);
- "
- [(set_attr "length" "12")
- (set_attr "type" "call")]
-)
-
-(define_insn "*call_value_reg_thumb_v5"
- [(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
- (match_operand 2 "" "")))
- (use (match_operand 3 "" ""))
- (clobber (reg:SI LR_REGNUM))]
- "TARGET_THUMB && arm_arch5"
- "blx\\t%1"
- [(set_attr "length" "2")
- (set_attr "type" "call")]
-)
-
-(define_insn "*call_value_reg_thumb"
- [(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
- (match_operand 2 "" "")))
- (use (match_operand 3 "" ""))
- (clobber (reg:SI LR_REGNUM))]
- "TARGET_THUMB && !arm_arch5"
- "*
- {
- if (!TARGET_CALLER_INTERWORKING)
- return thumb_call_via_reg (operands[1]);
- else if (operands[2] == const0_rtx)
- return \"bl\\t%__interwork_call_via_%1\";
- else if (frame_pointer_needed)
- return \"bl\\t%__interwork_r7_call_via_%1\";
- else
- return \"bl\\t%__interwork_r11_call_via_%1\";
- }"
- [(set_attr "type" "call")]
-)
-
-;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
-;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
-
-(define_insn "*call_symbol"
- [(call (mem:SI (match_operand:SI 0 "" ""))
- (match_operand 1 "" ""))
- (use (match_operand 2 "" ""))
- (clobber (reg:SI LR_REGNUM))]
- "TARGET_ARM
- && (GET_CODE (operands[0]) == SYMBOL_REF)
- && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
- "*
- {
- return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
- }"
- [(set_attr "type" "call")]
-)
-
-(define_insn "*call_value_symbol"
- [(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:SI 1 "" ""))
- (match_operand:SI 2 "" "")))
- (use (match_operand 3 "" ""))
- (clobber (reg:SI LR_REGNUM))]
- "TARGET_ARM
- && (GET_CODE (operands[1]) == SYMBOL_REF)
- && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
- "*
- {
- return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
- }"
- [(set_attr "type" "call")]
-)
-
-(define_insn "*call_insn"
- [(call (mem:SI (match_operand:SI 0 "" ""))
- (match_operand:SI 1 "" ""))
- (use (match_operand 2 "" ""))
- (clobber (reg:SI LR_REGNUM))]
- "TARGET_THUMB
- && GET_CODE (operands[0]) == SYMBOL_REF
- && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
- "bl\\t%a0"
- [(set_attr "length" "4")
- (set_attr "type" "call")]
-)
-
-(define_insn "*call_value_insn"
- [(set (match_operand 0 "" "")
- (call (mem:SI (match_operand 1 "" ""))
- (match_operand 2 "" "")))
- (use (match_operand 3 "" ""))
- (clobber (reg:SI LR_REGNUM))]
- "TARGET_THUMB
- && GET_CODE (operands[1]) == SYMBOL_REF
- && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
- "bl\\t%a1"
- [(set_attr "length" "4")
- (set_attr "type" "call")]
-)
-
-;; We may also be able to do sibcalls for Thumb, but it's much harder...
-(define_expand "sibcall"
- [(parallel [(call (match_operand 0 "memory_operand" "")
- (match_operand 1 "general_operand" ""))
- (return)
- (use (match_operand 2 "" ""))])]
- "TARGET_ARM"
- "
- {
- if (operands[2] == NULL_RTX)
- operands[2] = const0_rtx;
- }"
-)
-
-(define_expand "sibcall_value"
- [(parallel [(set (match_operand 0 "" "")
- (call (match_operand 1 "memory_operand" "")
- (match_operand 2 "general_operand" "")))
- (return)
- (use (match_operand 3 "" ""))])]
- "TARGET_ARM"
- "
- {
- if (operands[3] == NULL_RTX)
- operands[3] = const0_rtx;
- }"
-)
-
-(define_insn "*sibcall_insn"
- [(call (mem:SI (match_operand:SI 0 "" "X"))
- (match_operand 1 "" ""))
- (return)
- (use (match_operand 2 "" ""))]
- "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
- "*
- return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
- "
- [(set_attr "type" "call")]
-)
-
-(define_insn "*sibcall_value_insn"
- [(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:SI 1 "" "X"))
- (match_operand 2 "" "")))
- (return)
- (use (match_operand 3 "" ""))]
- "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
- "*
- return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
- "
- [(set_attr "type" "call")]
-)
-
-;; Often the return insn will be the same as loading from memory, so set attr
-(define_insn "return"
- [(return)]
- "TARGET_ARM && USE_RETURN_INSN (FALSE)"
- "*
- {
- if (arm_ccfsm_state == 2)
- {
- arm_ccfsm_state += 2;
- return \"\";
- }
- return output_return_instruction (const_true_rtx, TRUE, FALSE);
- }"
- [(set_attr "type" "load1")
- (set_attr "length" "12")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*cond_return"
- [(set (pc)
- (if_then_else (match_operator 0 "arm_comparison_operator"
- [(match_operand 1 "cc_register" "") (const_int 0)])
- (return)
- (pc)))]
- "TARGET_ARM && USE_RETURN_INSN (TRUE)"
- "*
- {
- if (arm_ccfsm_state == 2)
- {
- arm_ccfsm_state += 2;
- return \"\";
- }
- return output_return_instruction (operands[0], TRUE, FALSE);
- }"
- [(set_attr "conds" "use")
- (set_attr "length" "12")
- (set_attr "type" "load1")]
-)
-
-(define_insn "*cond_return_inverted"
- [(set (pc)
- (if_then_else (match_operator 0 "arm_comparison_operator"
- [(match_operand 1 "cc_register" "") (const_int 0)])
- (pc)
- (return)))]
- "TARGET_ARM && USE_RETURN_INSN (TRUE)"
- "*
- {
- if (arm_ccfsm_state == 2)
- {
- arm_ccfsm_state += 2;
- return \"\";
- }
- return output_return_instruction (operands[0], TRUE, TRUE);
- }"
- [(set_attr "conds" "use")
- (set_attr "length" "12")
- (set_attr "type" "load1")]
-)
-
-;; Generate a sequence of instructions to determine if the processor is
-;; in 26-bit or 32-bit mode, and return the appropriate return address
-;; mask.
-
-(define_expand "return_addr_mask"
- [(set (match_dup 1)
- (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
- (const_int 0)))
- (set (match_operand:SI 0 "s_register_operand" "")
- (if_then_else:SI (eq (match_dup 1) (const_int 0))
- (const_int -1)
- (const_int 67108860)))] ; 0x03fffffc
- "TARGET_ARM"
- "
- operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
- ")
-
-(define_insn "*check_arch2"
- [(set (match_operand:CC_NOOV 0 "cc_register" "")
- (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
- (const_int 0)))]
- "TARGET_ARM"
- "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
- [(set_attr "length" "8")
- (set_attr "conds" "set")]
-)
-
-;; Call subroutine returning any type.
-
-(define_expand "untyped_call"
- [(parallel [(call (match_operand 0 "" "")
- (const_int 0))
- (match_operand 1 "" "")
- (match_operand 2 "" "")])]
- "TARGET_EITHER"
- "
- {
- int i;
- rtx par = gen_rtx_PARALLEL (VOIDmode,
- rtvec_alloc (XVECLEN (operands[2], 0)));
- rtx addr = gen_reg_rtx (Pmode);
- rtx mem;
- int size = 0;
-
- emit_move_insn (addr, XEXP (operands[1], 0));
- mem = change_address (operands[1], BLKmode, addr);
-
- for (i = 0; i < XVECLEN (operands[2], 0); i++)
- {
- rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
-
- /* Default code only uses r0 as a return value, but we could
- be using anything up to 4 registers. */
- if (REGNO (src) == R0_REGNUM)
- src = gen_rtx_REG (TImode, R0_REGNUM);
-
- XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
- GEN_INT (size));
- size += GET_MODE_SIZE (GET_MODE (src));
- }
-
- emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
- const0_rtx));
-
- size = 0;
-
- for (i = 0; i < XVECLEN (par, 0); i++)
- {
- HOST_WIDE_INT offset = 0;
- rtx reg = XEXP (XVECEXP (par, 0, i), 0);
-
- if (size != 0)
- emit_move_insn (addr, plus_constant (addr, size));
-
- mem = change_address (mem, GET_MODE (reg), NULL);
- if (REGNO (reg) == R0_REGNUM)
- {
- /* On thumb we have to use a write-back instruction. */
- emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
- TARGET_THUMB ? TRUE : FALSE, mem, &offset));
- size = TARGET_ARM ? 16 : 0;
- }
- else
- {
- emit_move_insn (mem, reg);
- size = GET_MODE_SIZE (GET_MODE (reg));
- }
- }
-
- /* The optimizer does not know that the call sets the function value
- registers we stored in the result block. We avoid problems by
- claiming that all hard registers are used and clobbered at this
- point. */
- emit_insn (gen_blockage ());
-
- DONE;
- }"
-)
-
-(define_expand "untyped_return"
- [(match_operand:BLK 0 "memory_operand" "")
- (match_operand 1 "" "")]
- "TARGET_EITHER"
- "
- {
- int i;
- rtx addr = gen_reg_rtx (Pmode);
- rtx mem;
- int size = 0;
-
- emit_move_insn (addr, XEXP (operands[0], 0));
- mem = change_address (operands[0], BLKmode, addr);
-
- for (i = 0; i < XVECLEN (operands[1], 0); i++)
- {
- HOST_WIDE_INT offset = 0;
- rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
-
- if (size != 0)
- emit_move_insn (addr, plus_constant (addr, size));
-
- mem = change_address (mem, GET_MODE (reg), NULL);
- if (REGNO (reg) == R0_REGNUM)
- {
- /* On thumb we have to use a write-back instruction. */
- emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
- TARGET_THUMB ? TRUE : FALSE, mem, &offset));
- size = TARGET_ARM ? 16 : 0;
- }
- else
- {
- emit_move_insn (reg, mem);
- size = GET_MODE_SIZE (GET_MODE (reg));
- }
- }
-
- /* Emit USE insns before the return. */
- for (i = 0; i < XVECLEN (operands[1], 0); i++)
- emit_insn (gen_rtx_USE (VOIDmode,
- SET_DEST (XVECEXP (operands[1], 0, i))));
-
- /* Construct the return. */
- expand_naked_return ();
-
- DONE;
- }"
-)
-
-;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
-;; all of memory. This blocks insns from being moved across this point.
-
-(define_insn "blockage"
- [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
- "TARGET_EITHER"
- ""
- [(set_attr "length" "0")
- (set_attr "type" "block")]
-)
-
-(define_expand "casesi"
- [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
- (match_operand:SI 1 "const_int_operand" "") ; lower bound
- (match_operand:SI 2 "const_int_operand" "") ; total range
- (match_operand:SI 3 "" "") ; table label
- (match_operand:SI 4 "" "")] ; Out of range label
- "TARGET_ARM"
- "
- {
- rtx reg;
- if (operands[1] != const0_rtx)
- {
- reg = gen_reg_rtx (SImode);
-
- emit_insn (gen_addsi3 (reg, operands[0],
- GEN_INT (-INTVAL (operands[1]))));
- operands[0] = reg;
- }
-
- if (!const_ok_for_arm (INTVAL (operands[2])))
- operands[2] = force_reg (SImode, operands[2]);
-
- emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
- operands[4]));
- DONE;
- }"
-)
-
-;; The USE in this pattern is needed to tell flow analysis that this is
-;; a CASESI insn. It has no other purpose.
-(define_insn "casesi_internal"
- [(parallel [(set (pc)
- (if_then_else
- (leu (match_operand:SI 0 "s_register_operand" "r")
- (match_operand:SI 1 "arm_rhs_operand" "rI"))
- (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
- (label_ref (match_operand 2 "" ""))))
- (label_ref (match_operand 3 "" ""))))
- (clobber (reg:CC CC_REGNUM))
- (use (label_ref (match_dup 2)))])]
- "TARGET_ARM"
- "*
- if (flag_pic)
- return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
- return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
- "
- [(set_attr "conds" "clob")
- (set_attr "length" "12")]
-)
-
-(define_expand "indirect_jump"
- [(set (pc)
- (match_operand:SI 0 "s_register_operand" ""))]
- "TARGET_EITHER"
- ""
-)
-
-;; NB Never uses BX.
-(define_insn "*arm_indirect_jump"
- [(set (pc)
- (match_operand:SI 0 "s_register_operand" "r"))]
- "TARGET_ARM"
- "mov%?\\t%|pc, %0\\t%@ indirect register jump"
- [(set_attr "predicable" "yes")]
-)
-
-(define_insn "*load_indirect_jump"
- [(set (pc)
- (match_operand:SI 0 "memory_operand" "m"))]
- "TARGET_ARM"
- "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
- [(set_attr "type" "load1")
- (set_attr "pool_range" "4096")
- (set_attr "neg_pool_range" "4084")
- (set_attr "predicable" "yes")]
-)
-
-;; NB Never uses BX.
-(define_insn "*thumb_indirect_jump"
- [(set (pc)
- (match_operand:SI 0 "register_operand" "l*r"))]
- "TARGET_THUMB"
- "mov\\tpc, %0"
- [(set_attr "conds" "clob")
- (set_attr "length" "2")]
-)
-
-
-;; Misc insns
-
-(define_insn "nop"
- [(const_int 0)]
- "TARGET_EITHER"
- "*
- if (TARGET_ARM)
- return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
- return \"mov\\tr8, r8\";
- "
- [(set (attr "length")
- (if_then_else (eq_attr "is_thumb" "yes")
- (const_int 2)
- (const_int 4)))]
-)
-
-
-;; Patterns to allow combination of arithmetic, cond code and shifts
-
-(define_insn "*arith_shiftsi"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (match_operator:SI 1 "shiftable_operator"
- [(match_operator:SI 3 "shift_operator"
- [(match_operand:SI 4 "s_register_operand" "r")
- (match_operand:SI 5 "reg_or_int_operand" "rI")])
- (match_operand:SI 2 "s_register_operand" "r")]))]
- "TARGET_ARM"
- "%i1%?\\t%0, %2, %4%S3"
- [(set_attr "predicable" "yes")
- (set_attr "shift" "4")
- (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
- (const_string "alu_shift")
- (const_string "alu_shift_reg")))]
-)
-
-(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (match_operator:SI 1 "shiftable_operator"
- [(match_operator:SI 2 "shiftable_operator"
- [(match_operator:SI 3 "shift_operator"
- [(match_operand:SI 4 "s_register_operand" "")
- (match_operand:SI 5 "reg_or_int_operand" "")])
- (match_operand:SI 6 "s_register_operand" "")])
- (match_operand:SI 7 "arm_rhs_operand" "")]))
- (clobber (match_operand:SI 8 "s_register_operand" ""))]
- "TARGET_ARM"
- [(set (match_dup 8)
- (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
- (match_dup 6)]))
- (set (match_dup 0)
- (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
- "")
-
-(define_insn "*arith_shiftsi_compare0"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
- [(match_operator:SI 3 "shift_operator"
- [(match_operand:SI 4 "s_register_operand" "r")
- (match_operand:SI 5 "reg_or_int_operand" "rI")])
- (match_operand:SI 2 "s_register_operand" "r")])
- (const_int 0)))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
- (match_dup 2)]))]
- "TARGET_ARM"
- "%i1%?s\\t%0, %2, %4%S3"
- [(set_attr "conds" "set")
- (set_attr "shift" "4")
- (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
- (const_string "alu_shift")
- (const_string "alu_shift_reg")))]
-)
-
-(define_insn "*arith_shiftsi_compare0_scratch"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
- [(match_operator:SI 3 "shift_operator"
- [(match_operand:SI 4 "s_register_operand" "r")
- (match_operand:SI 5 "reg_or_int_operand" "rI")])
- (match_operand:SI 2 "s_register_operand" "r")])
- (const_int 0)))
- (clobber (match_scratch:SI 0 "=r"))]
- "TARGET_ARM"
- "%i1%?s\\t%0, %2, %4%S3"
- [(set_attr "conds" "set")
- (set_attr "shift" "4")
- (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
- (const_string "alu_shift")
- (const_string "alu_shift_reg")))]
-)
-
-(define_insn "*sub_shiftsi"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (minus:SI (match_operand:SI 1 "s_register_operand" "r")
- (match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
- "TARGET_ARM"
- "sub%?\\t%0, %1, %3%S2"
- [(set_attr "predicable" "yes")
- (set_attr "shift" "3")
- (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
- (const_string "alu_shift")
- (const_string "alu_shift_reg")))]
-)
-
-(define_insn "*sub_shiftsi_compare0"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV
- (minus:SI (match_operand:SI 1 "s_register_operand" "r")
- (match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "reg_or_int_operand" "rM")]))
- (const_int 0)))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
- (match_dup 4)])))]
- "TARGET_ARM"
- "sub%?s\\t%0, %1, %3%S2"
- [(set_attr "conds" "set")
- (set_attr "shift" "3")
- (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
- (const_string "alu_shift")
- (const_string "alu_shift_reg")))]
-)
-
-(define_insn "*sub_shiftsi_compare0_scratch"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV
- (minus:SI (match_operand:SI 1 "s_register_operand" "r")
- (match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "reg_or_int_operand" "rM")]))
- (const_int 0)))
- (clobber (match_scratch:SI 0 "=r"))]
- "TARGET_ARM"
- "sub%?s\\t%0, %1, %3%S2"
- [(set_attr "conds" "set")
- (set_attr "shift" "3")
- (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
- (const_string "alu_shift")
- (const_string "alu_shift_reg")))]
-)
-
-
-
-(define_insn "*and_scc"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (and:SI (match_operator:SI 1 "arm_comparison_operator"
- [(match_operand 3 "cc_register" "") (const_int 0)])
- (match_operand:SI 2 "s_register_operand" "r")))]
- "TARGET_ARM"
- "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
- [(set_attr "conds" "use")
- (set_attr "length" "8")]
-)
-
-(define_insn "*ior_scc"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (ior:SI (match_operator:SI 2 "arm_comparison_operator"
- [(match_operand 3 "cc_register" "") (const_int 0)])
- (match_operand:SI 1 "s_register_operand" "0,?r")))]
- "TARGET_ARM"
- "@
- orr%d2\\t%0, %1, #1
- mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
- [(set_attr "conds" "use")
- (set_attr "length" "4,8")]
-)
-
-(define_insn "*compare_scc"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (match_operator:SI 1 "arm_comparison_operator"
- [(match_operand:SI 2 "s_register_operand" "r,r")
- (match_operand:SI 3 "arm_add_operand" "rI,L")]))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "*
- if (operands[3] == const0_rtx)
- {
- if (GET_CODE (operands[1]) == LT)
- return \"mov\\t%0, %2, lsr #31\";
-
- if (GET_CODE (operands[1]) == GE)
- return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
-
- if (GET_CODE (operands[1]) == EQ)
- return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
- }
-
- if (GET_CODE (operands[1]) == NE)
- {
- if (which_alternative == 1)
- return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
- return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
- }
- if (which_alternative == 1)
- output_asm_insn (\"cmn\\t%2, #%n3\", operands);
- else
- output_asm_insn (\"cmp\\t%2, %3\", operands);
- return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
- "
- [(set_attr "conds" "clob")
- (set_attr "length" "12")]
-)
-
-(define_insn "*cond_move"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
- (if_then_else:SI (match_operator 3 "equality_operator"
- [(match_operator 4 "arm_comparison_operator"
- [(match_operand 5 "cc_register" "") (const_int 0)])
- (const_int 0)])
- (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
- (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
- "TARGET_ARM"
- "*
- if (GET_CODE (operands[3]) == NE)
- {
- if (which_alternative != 1)
- output_asm_insn (\"mov%D4\\t%0, %2\", operands);
- if (which_alternative != 0)
- output_asm_insn (\"mov%d4\\t%0, %1\", operands);
- return \"\";
- }
- if (which_alternative != 0)
- output_asm_insn (\"mov%D4\\t%0, %1\", operands);
- if (which_alternative != 1)
- output_asm_insn (\"mov%d4\\t%0, %2\", operands);
- return \"\";
- "
- [(set_attr "conds" "use")
- (set_attr "length" "4,4,8")]
-)
-
-(define_insn "*cond_arith"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (match_operator:SI 5 "shiftable_operator"
- [(match_operator:SI 4 "arm_comparison_operator"
- [(match_operand:SI 2 "s_register_operand" "r,r")
- (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
- (match_operand:SI 1 "s_register_operand" "0,?r")]))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "*
- if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
- return \"%i5\\t%0, %1, %2, lsr #31\";
-
- output_asm_insn (\"cmp\\t%2, %3\", operands);
- if (GET_CODE (operands[5]) == AND)
- output_asm_insn (\"mov%D4\\t%0, #0\", operands);
- else if (GET_CODE (operands[5]) == MINUS)
- output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
- else if (which_alternative != 0)
- output_asm_insn (\"mov%D4\\t%0, %1\", operands);
- return \"%i5%d4\\t%0, %1, #1\";
- "
- [(set_attr "conds" "clob")
- (set_attr "length" "12")]
-)
-
-(define_insn "*cond_sub"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
- (match_operator:SI 4 "arm_comparison_operator"
- [(match_operand:SI 2 "s_register_operand" "r,r")
- (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "*
- output_asm_insn (\"cmp\\t%2, %3\", operands);
- if (which_alternative != 0)
- output_asm_insn (\"mov%D4\\t%0, %1\", operands);
- return \"sub%d4\\t%0, %1, #1\";
- "
- [(set_attr "conds" "clob")
- (set_attr "length" "8,12")]
-)
-
-(define_insn "*cmp_ite0"
- [(set (match_operand 6 "dominant_cc_register" "")
- (compare
- (if_then_else:SI
- (match_operator 4 "arm_comparison_operator"
- [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
- (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
- (match_operator:SI 5 "arm_comparison_operator"
- [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
- (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
- (const_int 0))
- (const_int 0)))]
- "TARGET_ARM"
- "*
- {
- static const char * const opcodes[4][2] =
- {
- {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
- \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
- {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
- \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
- {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
- \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
- {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
- \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
- };
- int swap =
- comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
-
- return opcodes[which_alternative][swap];
- }"
- [(set_attr "conds" "set")
- (set_attr "length" "8")]
-)
-
-(define_insn "*cmp_ite1"
- [(set (match_operand 6 "dominant_cc_register" "")
- (compare
- (if_then_else:SI
- (match_operator 4 "arm_comparison_operator"
- [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
- (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
- (match_operator:SI 5 "arm_comparison_operator"
- [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
- (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
- (const_int 1))
- (const_int 0)))]
- "TARGET_ARM"
- "*
- {
- static const char * const opcodes[4][2] =
- {
- {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
- \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
- {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
- \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
- {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
- \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
- {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
- \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
- };
- int swap =
- comparison_dominates_p (GET_CODE (operands[5]),
- reverse_condition (GET_CODE (operands[4])));
-
- return opcodes[which_alternative][swap];
- }"
- [(set_attr "conds" "set")
- (set_attr "length" "8")]
-)
-
-(define_insn "*cmp_and"
- [(set (match_operand 6 "dominant_cc_register" "")
- (compare
- (and:SI
- (match_operator 4 "arm_comparison_operator"
- [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
- (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
- (match_operator:SI 5 "arm_comparison_operator"
- [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
- (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
- (const_int 0)))]
- "TARGET_ARM"
- "*
- {
- static const char *const opcodes[4][2] =
- {
- {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
- \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
- {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
- \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
- {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
- \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
- {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
- \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
- };
- int swap =
- comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
-
- return opcodes[which_alternative][swap];
- }"
- [(set_attr "conds" "set")
- (set_attr "predicable" "no")
- (set_attr "length" "8")]
-)
-
-(define_insn "*cmp_ior"
- [(set (match_operand 6 "dominant_cc_register" "")
- (compare
- (ior:SI
- (match_operator 4 "arm_comparison_operator"
- [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
- (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
- (match_operator:SI 5 "arm_comparison_operator"
- [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
- (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
- (const_int 0)))]
- "TARGET_ARM"
- "*
-{
- static const char *const opcodes[4][2] =
- {
- {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
- \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
- {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
- \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
- {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
- \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
- {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
- \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
- };
- int swap =
- comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
-
- return opcodes[which_alternative][swap];
-}
-"
- [(set_attr "conds" "set")
- (set_attr "length" "8")]
-)
-
-(define_insn_and_split "*ior_scc_scc"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (ior:SI (match_operator:SI 3 "arm_comparison_operator"
- [(match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "arm_add_operand" "rIL")])
- (match_operator:SI 6 "arm_comparison_operator"
- [(match_operand:SI 4 "s_register_operand" "r")
- (match_operand:SI 5 "arm_add_operand" "rIL")])))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM
- && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
- != CCmode)"
- "#"
- "TARGET_ARM && reload_completed"
- [(set (match_dup 7)
- (compare
- (ior:SI
- (match_op_dup 3 [(match_dup 1) (match_dup 2)])
- (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
- (const_int 0)))
- (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
- "operands[7]
- = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
- DOM_CC_X_OR_Y),
- CC_REGNUM);"
- [(set_attr "conds" "clob")
- (set_attr "length" "16")])
-
-; If the above pattern is followed by a CMP insn, then the compare is
-; redundant, since we can rework the conditional instruction that follows.
-(define_insn_and_split "*ior_scc_scc_cmp"
- [(set (match_operand 0 "dominant_cc_register" "")
- (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
- [(match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "arm_add_operand" "rIL")])
- (match_operator:SI 6 "arm_comparison_operator"
- [(match_operand:SI 4 "s_register_operand" "r")
- (match_operand:SI 5 "arm_add_operand" "rIL")]))
- (const_int 0)))
- (set (match_operand:SI 7 "s_register_operand" "=r")
- (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
- (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
- "TARGET_ARM"
- "#"
- "TARGET_ARM && reload_completed"
- [(set (match_dup 0)
- (compare
- (ior:SI
- (match_op_dup 3 [(match_dup 1) (match_dup 2)])
- (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
- (const_int 0)))
- (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
- ""
- [(set_attr "conds" "set")
- (set_attr "length" "16")])
-
-(define_insn_and_split "*and_scc_scc"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (and:SI (match_operator:SI 3 "arm_comparison_operator"
- [(match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "arm_add_operand" "rIL")])
- (match_operator:SI 6 "arm_comparison_operator"
- [(match_operand:SI 4 "s_register_operand" "r")
- (match_operand:SI 5 "arm_add_operand" "rIL")])))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM
- && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
- != CCmode)"
- "#"
- "TARGET_ARM && reload_completed
- && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
- != CCmode)"
- [(set (match_dup 7)
- (compare
- (and:SI
- (match_op_dup 3 [(match_dup 1) (match_dup 2)])
- (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
- (const_int 0)))
- (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
- "operands[7]
- = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
- DOM_CC_X_AND_Y),
- CC_REGNUM);"
- [(set_attr "conds" "clob")
- (set_attr "length" "16")])
-
-; If the above pattern is followed by a CMP insn, then the compare is
-; redundant, since we can rework the conditional instruction that follows.
-(define_insn_and_split "*and_scc_scc_cmp"
- [(set (match_operand 0 "dominant_cc_register" "")
- (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
- [(match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "arm_add_operand" "rIL")])
- (match_operator:SI 6 "arm_comparison_operator"
- [(match_operand:SI 4 "s_register_operand" "r")
- (match_operand:SI 5 "arm_add_operand" "rIL")]))
- (const_int 0)))
- (set (match_operand:SI 7 "s_register_operand" "=r")
- (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
- (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
- "TARGET_ARM"
- "#"
- "TARGET_ARM && reload_completed"
- [(set (match_dup 0)
- (compare
- (and:SI
- (match_op_dup 3 [(match_dup 1) (match_dup 2)])
- (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
- (const_int 0)))
- (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
- ""
- [(set_attr "conds" "set")
- (set_attr "length" "16")])
-
-;; If there is no dominance in the comparison, then we can still save an
-;; instruction in the AND case, since we can know that the second compare
-;; need only zero the value if false (if true, then the value is already
-;; correct).
-(define_insn_and_split "*and_scc_scc_nodom"
- [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
- (and:SI (match_operator:SI 3 "arm_comparison_operator"
- [(match_operand:SI 1 "s_register_operand" "r,r,0")
- (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
- (match_operator:SI 6 "arm_comparison_operator"
- [(match_operand:SI 4 "s_register_operand" "r,r,r")
- (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM
- && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
- == CCmode)"
- "#"
- "TARGET_ARM && reload_completed"
- [(parallel [(set (match_dup 0)
- (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
- (clobber (reg:CC CC_REGNUM))])
- (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
- (set (match_dup 0)
- (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
- (match_dup 0)
- (const_int 0)))]
- "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
- operands[4], operands[5]),
- CC_REGNUM);
- operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
- operands[5]);"
- [(set_attr "conds" "clob")
- (set_attr "length" "20")])
-
-(define_split
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (ior:SI
- (and:SI (match_operand:SI 0 "s_register_operand" "")
- (const_int 1))
- (match_operator:SI 1 "comparison_operator"
- [(match_operand:SI 2 "s_register_operand" "")
- (match_operand:SI 3 "arm_add_operand" "")]))
- (const_int 0)))
- (clobber (match_operand:SI 4 "s_register_operand" ""))]
- "TARGET_ARM"
- [(set (match_dup 4)
- (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
- (match_dup 0)))
- (set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
- (const_int 0)))]
- "")
-
-(define_split
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (ior:SI
- (match_operator:SI 1 "comparison_operator"
- [(match_operand:SI 2 "s_register_operand" "")
- (match_operand:SI 3 "arm_add_operand" "")])
- (and:SI (match_operand:SI 0 "s_register_operand" "")
- (const_int 1)))
- (const_int 0)))
- (clobber (match_operand:SI 4 "s_register_operand" ""))]
- "TARGET_ARM"
- [(set (match_dup 4)
- (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
- (match_dup 0)))
- (set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
- (const_int 0)))]
- "")
-
-(define_insn "*negscc"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (neg:SI (match_operator 3 "arm_comparison_operator"
- [(match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "arm_rhs_operand" "rI")])))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "*
- if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
- return \"mov\\t%0, %1, asr #31\";
-
- if (GET_CODE (operands[3]) == NE)
- return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
-
- if (GET_CODE (operands[3]) == GT)
- return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
-
- output_asm_insn (\"cmp\\t%1, %2\", operands);
- output_asm_insn (\"mov%D3\\t%0, #0\", operands);
- return \"mvn%d3\\t%0, #0\";
- "
- [(set_attr "conds" "clob")
- (set_attr "length" "12")]
-)
-
-(define_insn "movcond"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
- (if_then_else:SI
- (match_operator 5 "arm_comparison_operator"
- [(match_operand:SI 3 "s_register_operand" "r,r,r")
- (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
- (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
- (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "*
- if (GET_CODE (operands[5]) == LT
- && (operands[4] == const0_rtx))
- {
- if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
- {
- if (operands[2] == const0_rtx)
- return \"and\\t%0, %1, %3, asr #31\";
- return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
- }
- else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
- {
- if (operands[1] == const0_rtx)
- return \"bic\\t%0, %2, %3, asr #31\";
- return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
- }
- /* The only case that falls through to here is when both ops 1 & 2
- are constants. */
- }
-
- if (GET_CODE (operands[5]) == GE
- && (operands[4] == const0_rtx))
- {
- if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
- {
- if (operands[2] == const0_rtx)
- return \"bic\\t%0, %1, %3, asr #31\";
- return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
- }
- else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
- {
- if (operands[1] == const0_rtx)
- return \"and\\t%0, %2, %3, asr #31\";
- return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
- }
- /* The only case that falls through to here is when both ops 1 & 2
- are constants. */
- }
- if (GET_CODE (operands[4]) == CONST_INT
- && !const_ok_for_arm (INTVAL (operands[4])))
- output_asm_insn (\"cmn\\t%3, #%n4\", operands);
- else
- output_asm_insn (\"cmp\\t%3, %4\", operands);
- if (which_alternative != 0)
- output_asm_insn (\"mov%d5\\t%0, %1\", operands);
- if (which_alternative != 1)
- output_asm_insn (\"mov%D5\\t%0, %2\", operands);
- return \"\";
- "
- [(set_attr "conds" "clob")
- (set_attr "length" "8,8,12")]
-)
-
-(define_insn "*ifcompare_plus_move"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (if_then_else:SI (match_operator 6 "arm_comparison_operator"
- [(match_operand:SI 4 "s_register_operand" "r,r")
- (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
- (plus:SI
- (match_operand:SI 2 "s_register_operand" "r,r")
- (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
- (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "#"
- [(set_attr "conds" "clob")
- (set_attr "length" "8,12")]
-)
-
-(define_insn "*if_plus_move"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
- (if_then_else:SI
- (match_operator 4 "arm_comparison_operator"
- [(match_operand 5 "cc_register" "") (const_int 0)])
- (plus:SI
- (match_operand:SI 2 "s_register_operand" "r,r,r,r")
- (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
- (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
- "TARGET_ARM"
- "@
- add%d4\\t%0, %2, %3
- sub%d4\\t%0, %2, #%n3
- add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
- sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
- [(set_attr "conds" "use")
- (set_attr "length" "4,4,8,8")
- (set_attr "type" "*,*,*,*")]
-)
-
-(define_insn "*ifcompare_move_plus"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (if_then_else:SI (match_operator 6 "arm_comparison_operator"
- [(match_operand:SI 4 "s_register_operand" "r,r")
- (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
- (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
- (plus:SI
- (match_operand:SI 2 "s_register_operand" "r,r")
- (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "#"
- [(set_attr "conds" "clob")
- (set_attr "length" "8,12")]
-)
-
-(define_insn "*if_move_plus"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
- (if_then_else:SI
- (match_operator 4 "arm_comparison_operator"
- [(match_operand 5 "cc_register" "") (const_int 0)])
- (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
- (plus:SI
- (match_operand:SI 2 "s_register_operand" "r,r,r,r")
- (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
- "TARGET_ARM"
- "@
- add%D4\\t%0, %2, %3
- sub%D4\\t%0, %2, #%n3
- add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
- sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
- [(set_attr "conds" "use")
- (set_attr "length" "4,4,8,8")
- (set_attr "type" "*,*,*,*")]
-)
-
-(define_insn "*ifcompare_arith_arith"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (if_then_else:SI (match_operator 9 "arm_comparison_operator"
- [(match_operand:SI 5 "s_register_operand" "r")
- (match_operand:SI 6 "arm_add_operand" "rIL")])
- (match_operator:SI 8 "shiftable_operator"
- [(match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "arm_rhs_operand" "rI")])
- (match_operator:SI 7 "shiftable_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "arm_rhs_operand" "rI")])))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "#"
- [(set_attr "conds" "clob")
- (set_attr "length" "12")]
-)
-
-(define_insn "*if_arith_arith"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (if_then_else:SI (match_operator 5 "arm_comparison_operator"
- [(match_operand 8 "cc_register" "") (const_int 0)])
- (match_operator:SI 6 "shiftable_operator"
- [(match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "arm_rhs_operand" "rI")])
- (match_operator:SI 7 "shiftable_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
- "TARGET_ARM"
- "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
- [(set_attr "conds" "use")
- (set_attr "length" "8")]
-)
-
-(define_insn "*ifcompare_arith_move"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (if_then_else:SI (match_operator 6 "arm_comparison_operator"
- [(match_operand:SI 2 "s_register_operand" "r,r")
- (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
- (match_operator:SI 7 "shiftable_operator"
- [(match_operand:SI 4 "s_register_operand" "r,r")
- (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
- (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "*
- /* If we have an operation where (op x 0) is the identity operation and
- the conditional operator is LT or GE and we are comparing against zero and
- everything is in registers then we can do this in two instructions. */
- if (operands[3] == const0_rtx
- && GET_CODE (operands[7]) != AND
- && GET_CODE (operands[5]) == REG
- && GET_CODE (operands[1]) == REG
- && REGNO (operands[1]) == REGNO (operands[4])
- && REGNO (operands[4]) != REGNO (operands[0]))
- {
- if (GET_CODE (operands[6]) == LT)
- return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
- else if (GET_CODE (operands[6]) == GE)
- return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
- }
- if (GET_CODE (operands[3]) == CONST_INT
- && !const_ok_for_arm (INTVAL (operands[3])))
- output_asm_insn (\"cmn\\t%2, #%n3\", operands);
- else
- output_asm_insn (\"cmp\\t%2, %3\", operands);
- output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
- if (which_alternative != 0)
- return \"mov%D6\\t%0, %1\";
- return \"\";
- "
- [(set_attr "conds" "clob")
- (set_attr "length" "8,12")]
-)
-
-(define_insn "*if_arith_move"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (if_then_else:SI (match_operator 4 "arm_comparison_operator"
- [(match_operand 6 "cc_register" "") (const_int 0)])
- (match_operator:SI 5 "shiftable_operator"
- [(match_operand:SI 2 "s_register_operand" "r,r")
- (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
- (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
- "TARGET_ARM"
- "@
- %I5%d4\\t%0, %2, %3
- %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
- [(set_attr "conds" "use")
- (set_attr "length" "4,8")
- (set_attr "type" "*,*")]
-)
-
-(define_insn "*ifcompare_move_arith"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (if_then_else:SI (match_operator 6 "arm_comparison_operator"
- [(match_operand:SI 4 "s_register_operand" "r,r")
- (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
- (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
- (match_operator:SI 7 "shiftable_operator"
- [(match_operand:SI 2 "s_register_operand" "r,r")
- (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "*
- /* If we have an operation where (op x 0) is the identity operation and
- the conditional operator is LT or GE and we are comparing against zero and
- everything is in registers then we can do this in two instructions */
- if (operands[5] == const0_rtx
- && GET_CODE (operands[7]) != AND
- && GET_CODE (operands[3]) == REG
- && GET_CODE (operands[1]) == REG
- && REGNO (operands[1]) == REGNO (operands[2])
- && REGNO (operands[2]) != REGNO (operands[0]))
- {
- if (GET_CODE (operands[6]) == GE)
- return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
- else if (GET_CODE (operands[6]) == LT)
- return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
- }
-
- if (GET_CODE (operands[5]) == CONST_INT
- && !const_ok_for_arm (INTVAL (operands[5])))
- output_asm_insn (\"cmn\\t%4, #%n5\", operands);
- else
- output_asm_insn (\"cmp\\t%4, %5\", operands);
-
- if (which_alternative != 0)
- output_asm_insn (\"mov%d6\\t%0, %1\", operands);
- return \"%I7%D6\\t%0, %2, %3\";
- "
- [(set_attr "conds" "clob")
- (set_attr "length" "8,12")]
-)
-
-(define_insn "*if_move_arith"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (if_then_else:SI
- (match_operator 4 "arm_comparison_operator"
- [(match_operand 6 "cc_register" "") (const_int 0)])
- (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
- (match_operator:SI 5 "shiftable_operator"
- [(match_operand:SI 2 "s_register_operand" "r,r")
- (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
- "TARGET_ARM"
- "@
- %I5%D4\\t%0, %2, %3
- %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
- [(set_attr "conds" "use")
- (set_attr "length" "4,8")
- (set_attr "type" "*,*")]
-)
-
-(define_insn "*ifcompare_move_not"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (if_then_else:SI
- (match_operator 5 "arm_comparison_operator"
- [(match_operand:SI 3 "s_register_operand" "r,r")
- (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
- (match_operand:SI 1 "arm_not_operand" "0,?rIK")
- (not:SI
- (match_operand:SI 2 "s_register_operand" "r,r"))))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "#"
- [(set_attr "conds" "clob")
- (set_attr "length" "8,12")]
-)
-
-(define_insn "*if_move_not"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
- (if_then_else:SI
- (match_operator 4 "arm_comparison_operator"
- [(match_operand 3 "cc_register" "") (const_int 0)])
- (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
- (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
- "TARGET_ARM"
- "@
- mvn%D4\\t%0, %2
- mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
- mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
- [(set_attr "conds" "use")
- (set_attr "length" "4,8,8")]
-)
-
-(define_insn "*ifcompare_not_move"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (if_then_else:SI
- (match_operator 5 "arm_comparison_operator"
- [(match_operand:SI 3 "s_register_operand" "r,r")
- (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
- (not:SI
- (match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "#"
- [(set_attr "conds" "clob")
- (set_attr "length" "8,12")]
-)
-
-(define_insn "*if_not_move"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
- (if_then_else:SI
- (match_operator 4 "arm_comparison_operator"
- [(match_operand 3 "cc_register" "") (const_int 0)])
- (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
- (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
- "TARGET_ARM"
- "@
- mvn%d4\\t%0, %2
- mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
- mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
- [(set_attr "conds" "use")
- (set_attr "length" "4,8,8")]
-)
-
-(define_insn "*ifcompare_shift_move"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (if_then_else:SI
- (match_operator 6 "arm_comparison_operator"
- [(match_operand:SI 4 "s_register_operand" "r,r")
- (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
- (match_operator:SI 7 "shift_operator"
- [(match_operand:SI 2 "s_register_operand" "r,r")
- (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
- (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "#"
- [(set_attr "conds" "clob")
- (set_attr "length" "8,12")]
-)
-
-(define_insn "*if_shift_move"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
- (if_then_else:SI
- (match_operator 5 "arm_comparison_operator"
- [(match_operand 6 "cc_register" "") (const_int 0)])
- (match_operator:SI 4 "shift_operator"
- [(match_operand:SI 2 "s_register_operand" "r,r,r")
- (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
- (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
- "TARGET_ARM"
- "@
- mov%d5\\t%0, %2%S4
- mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
- mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
- [(set_attr "conds" "use")
- (set_attr "shift" "2")
- (set_attr "length" "4,8,8")
- (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
- (const_string "alu_shift")
- (const_string "alu_shift_reg")))]
-)
-
-(define_insn "*ifcompare_move_shift"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (if_then_else:SI
- (match_operator 6 "arm_comparison_operator"
- [(match_operand:SI 4 "s_register_operand" "r,r")
- (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
- (match_operand:SI 1 "arm_not_operand" "0,?rIK")
- (match_operator:SI 7 "shift_operator"
- [(match_operand:SI 2 "s_register_operand" "r,r")
- (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "#"
- [(set_attr "conds" "clob")
- (set_attr "length" "8,12")]
-)
-
-(define_insn "*if_move_shift"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
- (if_then_else:SI
- (match_operator 5 "arm_comparison_operator"
- [(match_operand 6 "cc_register" "") (const_int 0)])
- (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
- (match_operator:SI 4 "shift_operator"
- [(match_operand:SI 2 "s_register_operand" "r,r,r")
- (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
- "TARGET_ARM"
- "@
- mov%D5\\t%0, %2%S4
- mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
- mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
- [(set_attr "conds" "use")
- (set_attr "shift" "2")
- (set_attr "length" "4,8,8")
- (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
- (const_string "alu_shift")
- (const_string "alu_shift_reg")))]
-)
-
-(define_insn "*ifcompare_shift_shift"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (if_then_else:SI
- (match_operator 7 "arm_comparison_operator"
- [(match_operand:SI 5 "s_register_operand" "r")
- (match_operand:SI 6 "arm_add_operand" "rIL")])
- (match_operator:SI 8 "shift_operator"
- [(match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "arm_rhs_operand" "rM")])
- (match_operator:SI 9 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "arm_rhs_operand" "rM")])))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "#"
- [(set_attr "conds" "clob")
- (set_attr "length" "12")]
-)
-
-(define_insn "*if_shift_shift"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (if_then_else:SI
- (match_operator 5 "arm_comparison_operator"
- [(match_operand 8 "cc_register" "") (const_int 0)])
- (match_operator:SI 6 "shift_operator"
- [(match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "arm_rhs_operand" "rM")])
- (match_operator:SI 7 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
- "TARGET_ARM"
- "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
- [(set_attr "conds" "use")
- (set_attr "shift" "1")
- (set_attr "length" "8")
- (set (attr "type") (if_then_else
- (and (match_operand 2 "const_int_operand" "")
- (match_operand 4 "const_int_operand" ""))
- (const_string "alu_shift")
- (const_string "alu_shift_reg")))]
-)
-
-(define_insn "*ifcompare_not_arith"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (if_then_else:SI
- (match_operator 6 "arm_comparison_operator"
- [(match_operand:SI 4 "s_register_operand" "r")
- (match_operand:SI 5 "arm_add_operand" "rIL")])
- (not:SI (match_operand:SI 1 "s_register_operand" "r"))
- (match_operator:SI 7 "shiftable_operator"
- [(match_operand:SI 2 "s_register_operand" "r")
- (match_operand:SI 3 "arm_rhs_operand" "rI")])))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "#"
- [(set_attr "conds" "clob")
- (set_attr "length" "12")]
-)
-
-(define_insn "*if_not_arith"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (if_then_else:SI
- (match_operator 5 "arm_comparison_operator"
- [(match_operand 4 "cc_register" "") (const_int 0)])
- (not:SI (match_operand:SI 1 "s_register_operand" "r"))
- (match_operator:SI 6 "shiftable_operator"
- [(match_operand:SI 2 "s_register_operand" "r")
- (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
- "TARGET_ARM"
- "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
- [(set_attr "conds" "use")
- (set_attr "length" "8")]
-)
-
-(define_insn "*ifcompare_arith_not"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (if_then_else:SI
- (match_operator 6 "arm_comparison_operator"
- [(match_operand:SI 4 "s_register_operand" "r")
- (match_operand:SI 5 "arm_add_operand" "rIL")])
- (match_operator:SI 7 "shiftable_operator"
- [(match_operand:SI 2 "s_register_operand" "r")
- (match_operand:SI 3 "arm_rhs_operand" "rI")])
- (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "#"
- [(set_attr "conds" "clob")
- (set_attr "length" "12")]
-)
-
-(define_insn "*if_arith_not"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (if_then_else:SI
- (match_operator 5 "arm_comparison_operator"
- [(match_operand 4 "cc_register" "") (const_int 0)])
- (match_operator:SI 6 "shiftable_operator"
- [(match_operand:SI 2 "s_register_operand" "r")
- (match_operand:SI 3 "arm_rhs_operand" "rI")])
- (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
- "TARGET_ARM"
- "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
- [(set_attr "conds" "use")
- (set_attr "length" "8")]
-)
-
-(define_insn "*ifcompare_neg_move"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (if_then_else:SI
- (match_operator 5 "arm_comparison_operator"
- [(match_operand:SI 3 "s_register_operand" "r,r")
- (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
- (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "#"
- [(set_attr "conds" "clob")
- (set_attr "length" "8,12")]
-)
-
-(define_insn "*if_neg_move"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
- (if_then_else:SI
- (match_operator 4 "arm_comparison_operator"
- [(match_operand 3 "cc_register" "") (const_int 0)])
- (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
- (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
- "TARGET_ARM"
- "@
- rsb%d4\\t%0, %2, #0
- mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
- mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
- [(set_attr "conds" "use")
- (set_attr "length" "4,8,8")]
-)
-
-(define_insn "*ifcompare_move_neg"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (if_then_else:SI
- (match_operator 5 "arm_comparison_operator"
- [(match_operand:SI 3 "s_register_operand" "r,r")
- (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
- (match_operand:SI 1 "arm_not_operand" "0,?rIK")
- (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "#"
- [(set_attr "conds" "clob")
- (set_attr "length" "8,12")]
-)
-
-(define_insn "*if_move_neg"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
- (if_then_else:SI
- (match_operator 4 "arm_comparison_operator"
- [(match_operand 3 "cc_register" "") (const_int 0)])
- (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
- (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
- "TARGET_ARM"
- "@
- rsb%D4\\t%0, %2, #0
- mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
- mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
- [(set_attr "conds" "use")
- (set_attr "length" "4,8,8")]
-)
-
-(define_insn "*arith_adjacentmem"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (match_operator:SI 1 "shiftable_operator"
- [(match_operand:SI 2 "memory_operand" "m")
- (match_operand:SI 3 "memory_operand" "m")]))
- (clobber (match_scratch:SI 4 "=r"))]
- "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
- "*
- {
- rtx ldm[3];
- rtx arith[4];
- rtx base_reg;
- HOST_WIDE_INT val1 = 0, val2 = 0;
-
- if (REGNO (operands[0]) > REGNO (operands[4]))
- {
- ldm[1] = operands[4];
- ldm[2] = operands[0];
- }
- else
- {
- ldm[1] = operands[0];
- ldm[2] = operands[4];
- }
-
- base_reg = XEXP (operands[2], 0);
-
- if (!REG_P (base_reg))
- {
- val1 = INTVAL (XEXP (base_reg, 1));
- base_reg = XEXP (base_reg, 0);
- }
-
- if (!REG_P (XEXP (operands[3], 0)))
- val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
-
- arith[0] = operands[0];
- arith[3] = operands[1];
-
- if (val1 < val2)
- {
- arith[1] = ldm[1];
- arith[2] = ldm[2];
- }
- else
- {
- arith[1] = ldm[2];
- arith[2] = ldm[1];
- }
-
- ldm[0] = base_reg;
- if (val1 !=0 && val2 != 0)
- {
- rtx ops[3];
-
- if (val1 == 4 || val2 == 4)
- /* Other val must be 8, since we know they are adjacent and neither
- is zero. */
- output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm);
- else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
- {
- ldm[0] = ops[0] = operands[4];
- ops[1] = base_reg;
- ops[2] = GEN_INT (val1);
- output_add_immediate (ops);
- if (val1 < val2)
- output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
- else
- output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
- }
- else
- {
- /* Offset is out of range for a single add, so use two ldr. */
- ops[0] = ldm[1];
- ops[1] = base_reg;
- ops[2] = GEN_INT (val1);
- output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
- ops[0] = ldm[2];
- ops[2] = GEN_INT (val2);
- output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
- }
- }
- else if (val1 != 0)
- {
- if (val1 < val2)
- output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
- else
- output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
- }
- else
- {
- if (val1 < val2)
- output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
- else
- output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
- }
- output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
- return \"\";
- }"
- [(set_attr "length" "12")
- (set_attr "predicable" "yes")
- (set_attr "type" "load1")]
-)
-
-; This pattern is never tried by combine, so do it as a peephole
-
-(define_peephole2
- [(set (match_operand:SI 0 "arm_general_register_operand" "")
- (match_operand:SI 1 "arm_general_register_operand" ""))
- (set (reg:CC CC_REGNUM)
- (compare:CC (match_dup 1) (const_int 0)))]
- "TARGET_ARM"
- [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
- (set (match_dup 0) (match_dup 1))])]
- ""
-)
-
-; Peepholes to spot possible load- and store-multiples, if the ordering is
-; reversed, check that the memory references aren't volatile.
-
-(define_peephole
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (match_operand:SI 4 "memory_operand" "m"))
- (set (match_operand:SI 1 "s_register_operand" "=r")
- (match_operand:SI 5 "memory_operand" "m"))
- (set (match_operand:SI 2 "s_register_operand" "=r")
- (match_operand:SI 6 "memory_operand" "m"))
- (set (match_operand:SI 3 "s_register_operand" "=r")
- (match_operand:SI 7 "memory_operand" "m"))]
- "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
- "*
- return emit_ldm_seq (operands, 4);
- "
-)
-
-(define_peephole
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (match_operand:SI 3 "memory_operand" "m"))
- (set (match_operand:SI 1 "s_register_operand" "=r")
- (match_operand:SI 4 "memory_operand" "m"))
- (set (match_operand:SI 2 "s_register_operand" "=r")
- (match_operand:SI 5 "memory_operand" "m"))]
- "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
- "*
- return emit_ldm_seq (operands, 3);
- "
-)
-
-(define_peephole
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (match_operand:SI 2 "memory_operand" "m"))
- (set (match_operand:SI 1 "s_register_operand" "=r")
- (match_operand:SI 3 "memory_operand" "m"))]
- "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
- "*
- return emit_ldm_seq (operands, 2);
- "
-)
-
-(define_peephole
- [(set (match_operand:SI 4 "memory_operand" "=m")
- (match_operand:SI 0 "s_register_operand" "r"))
- (set (match_operand:SI 5 "memory_operand" "=m")
- (match_operand:SI 1 "s_register_operand" "r"))
- (set (match_operand:SI 6 "memory_operand" "=m")
- (match_operand:SI 2 "s_register_operand" "r"))
- (set (match_operand:SI 7 "memory_operand" "=m")
- (match_operand:SI 3 "s_register_operand" "r"))]
- "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
- "*
- return emit_stm_seq (operands, 4);
- "
-)
-
-(define_peephole
- [(set (match_operand:SI 3 "memory_operand" "=m")
- (match_operand:SI 0 "s_register_operand" "r"))
- (set (match_operand:SI 4 "memory_operand" "=m")
- (match_operand:SI 1 "s_register_operand" "r"))
- (set (match_operand:SI 5 "memory_operand" "=m")
- (match_operand:SI 2 "s_register_operand" "r"))]
- "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
- "*
- return emit_stm_seq (operands, 3);
- "
-)
-
-(define_peephole
- [(set (match_operand:SI 2 "memory_operand" "=m")
- (match_operand:SI 0 "s_register_operand" "r"))
- (set (match_operand:SI 3 "memory_operand" "=m")
- (match_operand:SI 1 "s_register_operand" "r"))]
- "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
- "*
- return emit_stm_seq (operands, 2);
- "
-)
-
-(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
- (const_int 0))
- (neg:SI (match_operator:SI 2 "arm_comparison_operator"
- [(match_operand:SI 3 "s_register_operand" "")
- (match_operand:SI 4 "arm_rhs_operand" "")]))))
- (clobber (match_operand:SI 5 "s_register_operand" ""))]
- "TARGET_ARM"
- [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
- (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
- (match_dup 5)))]
- ""
-)
-
-;; This split can be used because CC_Z mode implies that the following
-;; branch will be an equality, or an unsigned inequality, so the sign
-;; extension is not needed.
-
-(define_split
- [(set (reg:CC_Z CC_REGNUM)
- (compare:CC_Z
- (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
- (const_int 24))
- (match_operand 1 "const_int_operand" "")))
- (clobber (match_scratch:SI 2 ""))]
- "TARGET_ARM
- && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
- == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
- [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
- (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
- "
- operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
- "
-)
-
-(define_expand "prologue"
- [(clobber (const_int 0))]
- "TARGET_EITHER"
- "if (TARGET_ARM)
- arm_expand_prologue ();
- else
- thumb_expand_prologue ();
- DONE;
- "
-)
-
-(define_expand "epilogue"
- [(clobber (const_int 0))]
- "TARGET_EITHER"
- "
- if (current_function_calls_eh_return)
- emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
- if (TARGET_THUMB)
- thumb_expand_epilogue ();
- else if (USE_RETURN_INSN (FALSE))
- {
- emit_jump_insn (gen_return ());
- DONE;
- }
- emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
- gen_rtvec (1,
- gen_rtx_RETURN (VOIDmode)),
- VUNSPEC_EPILOGUE));
- DONE;
- "
-)
-
-;; Note - although unspec_volatile's USE all hard registers,
-;; USEs are ignored after relaod has completed. Thus we need
-;; to add an unspec of the link register to ensure that flow
-;; does not think that it is unused by the sibcall branch that
-;; will replace the standard function epilogue.
-(define_insn "sibcall_epilogue"
- [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
- (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
- "TARGET_ARM"
- "*
- if (use_return_insn (FALSE, next_nonnote_insn (insn)))
- return output_return_instruction (const_true_rtx, FALSE, FALSE);
- return arm_output_epilogue (next_nonnote_insn (insn));
- "
-;; Length is absolute worst case
- [(set_attr "length" "44")
- (set_attr "type" "block")
- ;; We don't clobber the conditions, but the potential length of this
- ;; operation is sufficient to make conditionalizing the sequence
- ;; unlikely to be profitable.
- (set_attr "conds" "clob")]
-)
-
-(define_insn "*epilogue_insns"
- [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
- "TARGET_EITHER"
- "*
- if (TARGET_ARM)
- return arm_output_epilogue (NULL);
- else /* TARGET_THUMB */
- return thumb_unexpanded_epilogue ();
- "
- ; Length is absolute worst case
- [(set_attr "length" "44")
- (set_attr "type" "block")
- ;; We don't clobber the conditions, but the potential length of this
- ;; operation is sufficient to make conditionalizing the sequence
- ;; unlikely to be profitable.
- (set_attr "conds" "clob")]
-)
-
-(define_expand "eh_epilogue"
- [(use (match_operand:SI 0 "register_operand" ""))
- (use (match_operand:SI 1 "register_operand" ""))
- (use (match_operand:SI 2 "register_operand" ""))]
- "TARGET_EITHER"
- "
- {
- cfun->machine->eh_epilogue_sp_ofs = operands[1];
- if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
- {
- rtx ra = gen_rtx_REG (Pmode, 2);
-
- emit_move_insn (ra, operands[2]);
- operands[2] = ra;
- }
- /* This is a hack -- we may have crystalized the function type too
- early. */
- cfun->machine->func_type = 0;
- }"
-)
-
-;; This split is only used during output to reduce the number of patterns
-;; that need assembler instructions adding to them. We allowed the setting
-;; of the conditions to be implicit during rtl generation so that
-;; the conditional compare patterns would work. However this conflicts to
-;; some extent with the conditional data operations, so we have to split them
-;; up again here.
-
-(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (if_then_else:SI (match_operator 1 "arm_comparison_operator"
- [(match_operand 2 "" "") (match_operand 3 "" "")])
- (match_dup 0)
- (match_operand 4 "" "")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM && reload_completed"
- [(set (match_dup 5) (match_dup 6))
- (cond_exec (match_dup 7)
- (set (match_dup 0) (match_dup 4)))]
- "
- {
- enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
- operands[2], operands[3]);
- enum rtx_code rc = GET_CODE (operands[1]);
-
- operands[5] = gen_rtx_REG (mode, CC_REGNUM);
- operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
- if (mode == CCFPmode || mode == CCFPEmode)
- rc = reverse_condition_maybe_unordered (rc);
- else
- rc = reverse_condition (rc);
-
- operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
- }"
-)
-
-(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (if_then_else:SI (match_operator 1 "arm_comparison_operator"
- [(match_operand 2 "" "") (match_operand 3 "" "")])
- (match_operand 4 "" "")
- (match_dup 0)))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM && reload_completed"
- [(set (match_dup 5) (match_dup 6))
- (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
- (set (match_dup 0) (match_dup 4)))]
- "
- {
- enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
- operands[2], operands[3]);
-
- operands[5] = gen_rtx_REG (mode, CC_REGNUM);
- operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
- }"
-)
-
-(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (if_then_else:SI (match_operator 1 "arm_comparison_operator"
- [(match_operand 2 "" "") (match_operand 3 "" "")])
- (match_operand 4 "" "")
- (match_operand 5 "" "")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM && reload_completed"
- [(set (match_dup 6) (match_dup 7))
- (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
- (set (match_dup 0) (match_dup 4)))
- (cond_exec (match_dup 8)
- (set (match_dup 0) (match_dup 5)))]
- "
- {
- enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
- operands[2], operands[3]);
- enum rtx_code rc = GET_CODE (operands[1]);
-
- operands[6] = gen_rtx_REG (mode, CC_REGNUM);
- operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
- if (mode == CCFPmode || mode == CCFPEmode)
- rc = reverse_condition_maybe_unordered (rc);
- else
- rc = reverse_condition (rc);
-
- operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
- }"
-)
-
-(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (if_then_else:SI (match_operator 1 "arm_comparison_operator"
- [(match_operand:SI 2 "s_register_operand" "")
- (match_operand:SI 3 "arm_add_operand" "")])
- (match_operand:SI 4 "arm_rhs_operand" "")
- (not:SI
- (match_operand:SI 5 "s_register_operand" ""))))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM && reload_completed"
- [(set (match_dup 6) (match_dup 7))
- (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
- (set (match_dup 0) (match_dup 4)))
- (cond_exec (match_dup 8)
- (set (match_dup 0) (not:SI (match_dup 5))))]
- "
- {
- enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
- operands[2], operands[3]);
- enum rtx_code rc = GET_CODE (operands[1]);
-
- operands[6] = gen_rtx_REG (mode, CC_REGNUM);
- operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
- if (mode == CCFPmode || mode == CCFPEmode)
- rc = reverse_condition_maybe_unordered (rc);
- else
- rc = reverse_condition (rc);
-
- operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
- }"
-)
-
-(define_insn "*cond_move_not"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (if_then_else:SI (match_operator 4 "arm_comparison_operator"
- [(match_operand 3 "cc_register" "") (const_int 0)])
- (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
- (not:SI
- (match_operand:SI 2 "s_register_operand" "r,r"))))]
- "TARGET_ARM"
- "@
- mvn%D4\\t%0, %2
- mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
- [(set_attr "conds" "use")
- (set_attr "length" "4,8")]
-)
-
-;; The next two patterns occur when an AND operation is followed by a
-;; scc insn sequence
-
-(define_insn "*sign_extract_onebit"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
- (const_int 1)
- (match_operand:SI 2 "const_int_operand" "n")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "*
- operands[2] = GEN_INT (1 << INTVAL (operands[2]));
- output_asm_insn (\"ands\\t%0, %1, %2\", operands);
- return \"mvnne\\t%0, #0\";
- "
- [(set_attr "conds" "clob")
- (set_attr "length" "8")]
-)
-
-(define_insn "*not_signextract_onebit"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (not:SI
- (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
- (const_int 1)
- (match_operand:SI 2 "const_int_operand" "n"))))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "*
- operands[2] = GEN_INT (1 << INTVAL (operands[2]));
- output_asm_insn (\"tst\\t%1, %2\", operands);
- output_asm_insn (\"mvneq\\t%0, #0\", operands);
- return \"movne\\t%0, #0\";
- "
- [(set_attr "conds" "clob")
- (set_attr "length" "12")]
-)
-
-;; Push multiple registers to the stack. Registers are in parallel (use ...)
-;; expressions. For simplicity, the first register is also in the unspec
-;; part.
-(define_insn "*push_multi"
- [(match_parallel 2 "multi_register_push"
- [(set (match_operand:BLK 0 "memory_operand" "=m")
- (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
- UNSPEC_PUSH_MULT))])]
- "TARGET_ARM"
- "*
- {
- int num_saves = XVECLEN (operands[2], 0);
-
- /* For the StrongARM at least it is faster to
- use STR to store only a single register. */
- if (num_saves == 1)
- output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
- else
- {
- int i;
- char pattern[100];
-
- strcpy (pattern, \"stmfd\\t%m0!, {%1\");
-
- for (i = 1; i < num_saves; i++)
- {
- strcat (pattern, \", %|\");
- strcat (pattern,
- reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
- }
-
- strcat (pattern, \"}\");
- output_asm_insn (pattern, operands);
- }
-
- return \"\";
- }"
- [(set_attr "type" "store4")]
-)
-
-(define_insn "stack_tie"
- [(set (mem:BLK (scratch))
- (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
- (match_operand:SI 1 "s_register_operand" "r")]
- UNSPEC_PRLG_STK))]
- ""
- ""
- [(set_attr "length" "0")]
-)
-
-;; Similarly for the floating point registers
-(define_insn "*push_fp_multi"
- [(match_parallel 2 "multi_register_push"
- [(set (match_operand:BLK 0 "memory_operand" "=m")
- (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
- UNSPEC_PUSH_MULT))])]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "*
- {
- char pattern[100];
-
- sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
- output_asm_insn (pattern, operands);
- return \"\";
- }"
- [(set_attr "type" "f_store")]
-)
-
-;; Special patterns for dealing with the constant pool
-
-(define_insn "align_4"
- [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
- "TARGET_EITHER"
- "*
- assemble_align (32);
- return \"\";
- "
-)
-
-(define_insn "align_8"
- [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
- "TARGET_EITHER"
- "*
- assemble_align (64);
- return \"\";
- "
-)
-
-(define_insn "consttable_end"
- [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
- "TARGET_EITHER"
- "*
- making_const_table = FALSE;
- return \"\";
- "
-)
-
-(define_insn "consttable_1"
- [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
- "TARGET_THUMB"
- "*
- making_const_table = TRUE;
- assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
- assemble_zeros (3);
- return \"\";
- "
- [(set_attr "length" "4")]
-)
-
-(define_insn "consttable_2"
- [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
- "TARGET_THUMB"
- "*
- making_const_table = TRUE;
- assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
- assemble_zeros (2);
- return \"\";
- "
- [(set_attr "length" "4")]
-)
-
-(define_insn "consttable_4"
- [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
- "TARGET_EITHER"
- "*
- {
- making_const_table = TRUE;
- switch (GET_MODE_CLASS (GET_MODE (operands[0])))
- {
- case MODE_FLOAT:
- {
- REAL_VALUE_TYPE r;
- REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
- assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
- break;
- }
- default:
- assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
- break;
- }
- return \"\";
- }"
- [(set_attr "length" "4")]
-)
-
-(define_insn "consttable_8"
- [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
- "TARGET_EITHER"
- "*
- {
- making_const_table = TRUE;
- switch (GET_MODE_CLASS (GET_MODE (operands[0])))
- {
- case MODE_FLOAT:
- {
- REAL_VALUE_TYPE r;
- REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
- assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
- break;
- }
- default:
- assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
- break;
- }
- return \"\";
- }"
- [(set_attr "length" "8")]
-)
-
-;; Miscellaneous Thumb patterns
-
-(define_expand "tablejump"
- [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
- (use (label_ref (match_operand 1 "" "")))])]
- "TARGET_THUMB"
- "
- if (flag_pic)
- {
- /* Hopefully, CSE will eliminate this copy. */
- rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
- rtx reg2 = gen_reg_rtx (SImode);
-
- emit_insn (gen_addsi3 (reg2, operands[0], reg1));
- operands[0] = reg2;
- }
- "
-)
-
-;; NB never uses BX.
-(define_insn "*thumb_tablejump"
- [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
- (use (label_ref (match_operand 1 "" "")))]
- "TARGET_THUMB"
- "mov\\t%|pc, %0"
- [(set_attr "length" "2")]
-)
-
-;; V5 Instructions,
-
-(define_insn "clzsi2"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
- "TARGET_ARM && arm_arch5"
- "clz%?\\t%0, %1"
- [(set_attr "predicable" "yes")])
-
-(define_expand "ffssi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
- "TARGET_ARM && arm_arch5"
- "
- {
- rtx t1, t2, t3;
-
- t1 = gen_reg_rtx (SImode);
- t2 = gen_reg_rtx (SImode);
- t3 = gen_reg_rtx (SImode);
-
- emit_insn (gen_negsi2 (t1, operands[1]));
- emit_insn (gen_andsi3 (t2, operands[1], t1));
- emit_insn (gen_clzsi2 (t3, t2));
- emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
- DONE;
- }"
-)
-
-(define_expand "ctzsi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
- "TARGET_ARM && arm_arch5"
- "
- {
- rtx t1, t2, t3;
-
- t1 = gen_reg_rtx (SImode);
- t2 = gen_reg_rtx (SImode);
- t3 = gen_reg_rtx (SImode);
-
- emit_insn (gen_negsi2 (t1, operands[1]));
- emit_insn (gen_andsi3 (t2, operands[1], t1));
- emit_insn (gen_clzsi2 (t3, t2));
- emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
- DONE;
- }"
-)
-
-;; V5E instructions.
-
-(define_insn "prefetch"
- [(prefetch (match_operand:SI 0 "address_operand" "p")
- (match_operand:SI 1 "" "")
- (match_operand:SI 2 "" ""))]
- "TARGET_ARM && arm_arch5e"
- "pld\\t%a0")
-
-;; General predication pattern
-
-(define_cond_exec
- [(match_operator 0 "arm_comparison_operator"
- [(match_operand 1 "cc_register" "")
- (const_int 0)])]
- "TARGET_ARM"
- ""
-)
-
-(define_insn "prologue_use"
- [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
- ""
- "%@ %0 needed for prologue"
-)
-
-
-;; Patterns for exception handling
-
-(define_expand "eh_return"
- [(use (match_operand 0 "general_operand" ""))]
- "TARGET_EITHER"
- "
- {
- if (TARGET_ARM)
- emit_insn (gen_arm_eh_return (operands[0]));
- else
- emit_insn (gen_thumb_eh_return (operands[0]));
- DONE;
- }"
-)
-
-;; We can't expand this before we know where the link register is stored.
-(define_insn_and_split "arm_eh_return"
- [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
- VUNSPEC_EH_RETURN)
- (clobber (match_scratch:SI 1 "=&r"))]
- "TARGET_ARM"
- "#"
- "&& reload_completed"
- [(const_int 0)]
- "
- {
- arm_set_return_address (operands[0], operands[1]);
- DONE;
- }"
-)
-
-(define_insn_and_split "thumb_eh_return"
- [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
- VUNSPEC_EH_RETURN)
- (clobber (match_scratch:SI 1 "=&l"))]
- "TARGET_THUMB"
- "#"
- "&& reload_completed"
- [(const_int 0)]
- "
- {
- thumb_set_return_address (operands[0], operands[1]);
- DONE;
- }"
-)
-
-
-;; TLS support
-
-(define_insn "load_tp_hard"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(const_int 0)] UNSPEC_TLS))]
- "TARGET_HARD_TP"
- "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
- [(set_attr "predicable" "yes")]
-)
-
-;; Doesn't clobber R1-R3. Must use r0 for the first operand.
-(define_insn "load_tp_soft"
- [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
- (clobber (reg:SI LR_REGNUM))
- (clobber (reg:SI IP_REGNUM))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_SOFT_TP"
- "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
- [(set_attr "conds" "clob")]
-)
-
-;; Load the FPA co-processor patterns
-(include "fpa.md")
-;; Load the Maverick co-processor patterns
-(include "cirrus.md")
-;; Load the Intel Wireless Multimedia Extension patterns
-(include "iwmmxt.md")
-;; Load the VFP co-processor patterns
-(include "vfp.md")
-
diff --git a/gcc-4.2.1/gcc/config/arm/arm.opt b/gcc-4.2.1/gcc/config/arm/arm.opt
deleted file mode 100644
index 8f85ffb05..000000000
--- a/gcc-4.2.1/gcc/config/arm/arm.opt
+++ /dev/null
@@ -1,155 +0,0 @@
-; Options for the ARM port of the compiler.
-
-; Copyright (C) 2005 Free Software Foundation, Inc.
-;
-; This file is part of GCC.
-;
-; GCC is free software; you can redistribute it and/or modify it under
-; the terms of the GNU General Public License as published by the Free
-; Software Foundation; either version 2, or (at your option) any later
-; version.
-;
-; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-; WARRANTY; without even the implied warranty of MERCHANTABILITY or
-; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-; for more details.
-;
-; You should have received a copy of the GNU General Public License
-; along with GCC; see the file COPYING. If not, write to the Free
-; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-; 02110-1301, USA.
-
-mabi=
-Target RejectNegative Joined Var(target_abi_name)
-Specify an ABI
-
-mabort-on-noreturn
-Target Report Mask(ABORT_NORETURN)
-Generate a call to abort if a noreturn function returns
-
-mapcs
-Target RejectNegative Mask(APCS_FRAME) MaskExists Undocumented
-
-mapcs-float
-Target Report Mask(APCS_FLOAT)
-Pass FP arguments in FP registers
-
-mapcs-frame
-Target Report Mask(APCS_FRAME)
-Generate APCS conformant stack frames
-
-mapcs-reentrant
-Target Report Mask(APCS_REENT)
-Generate re-entrant, PIC code
-
-mapcs-stack-check
-Target Report Mask(APCS_STACK) Undocumented
-
-march=
-Target RejectNegative Joined
-Specify the name of the target architecture
-
-marm
-Target RejectNegative InverseMask(THUMB) Undocumented
-
-mbig-endian
-Target Report RejectNegative Mask(BIG_END)
-Assume target CPU is configured as big endian
-
-mcallee-super-interworking
-Target Report Mask(CALLEE_INTERWORKING)
-Thumb: Assume non-static functions may be called from ARM code
-
-mcaller-super-interworking
-Target Report Mask(CALLER_INTERWORKING)
-Thumb: Assume function pointers may go to non-Thumb aware code
-
-mcirrus-fix-invalid-insns
-Target Report Mask(CIRRUS_FIX_INVALID_INSNS)
-Cirrus: Place NOPs to avoid invalid instruction combinations
-
-mcpu=
-Target RejectNegative Joined
-Specify the name of the target CPU
-
-mfloat-abi=
-Target RejectNegative Joined Var(target_float_abi_name)
-Specify if floating point hardware should be used
-
-mfp=
-Target RejectNegative Joined Undocumented Var(target_fpe_name)
-
-;; Now ignored.
-mfpe
-Target RejectNegative Mask(FPE) Undocumented
-
-mfpe=
-Target RejectNegative Joined Undocumented Var(target_fpe_name)
-
-mfpu=
-Target RejectNegative Joined Var(target_fpu_name)
-Specify the name of the target floating point hardware/format
-
-mhard-float
-Target RejectNegative
-Alias for -mfloat-abi=hard
-
-mlittle-endian
-Target Report RejectNegative InverseMask(BIG_END)
-Assume target CPU is configured as little endian
-
-mlong-calls
-Target Report Mask(LONG_CALLS)
-Generate call insns as indirect calls, if necessary
-
-mpic-register=
-Target RejectNegative Joined Var(arm_pic_register_string)
-Specify the register to be used for PIC addressing
-
-mpoke-function-name
-Target Report Mask(POKE_FUNCTION_NAME)
-Store function names in object code
-
-msched-prolog
-Target Report Mask(SCHED_PROLOG)
-Permit scheduling of a function's prologue sequence
-
-msingle-pic-base
-Target Report Mask(SINGLE_PIC_BASE)
-Do not load the PIC register in function prologues
-
-msoft-float
-Target RejectNegative
-Alias for -mfloat-abi=soft
-
-mstructure-size-boundary=
-Target RejectNegative Joined Var(structure_size_string)
-Specify the minimum bit alignment of structures
-
-mthumb
-Target Report Mask(THUMB)
-Compile for the Thumb not the ARM
-
-mthumb-interwork
-Target Report Mask(INTERWORK)
-Support calls between Thumb and ARM instruction sets
-
-mtp=
-Target RejectNegative Joined Var(target_thread_switch)
-Specify how to access the thread pointer
-
-mtpcs-frame
-Target Report Mask(TPCS_FRAME)
-Thumb: Generate (non-leaf) stack frames even if not needed
-
-mtpcs-leaf-frame
-Target Report Mask(TPCS_LEAF_FRAME)
-Thumb: Generate (leaf) stack frames even if not needed
-
-mtune=
-Target RejectNegative Joined
-Tune code for the given processor
-
-mwords-little-endian
-Target Report RejectNegative Mask(LITTLE_WORDS)
-Assume big endian bytes, little endian words
diff --git a/gcc-4.2.1/gcc/config/arm/arm1020e.md b/gcc-4.2.1/gcc/config/arm/arm1020e.md
deleted file mode 100644
index 32a5d95e9..000000000
--- a/gcc-4.2.1/gcc/config/arm/arm1020e.md
+++ /dev/null
@@ -1,388 +0,0 @@
-;; ARM 1020E & ARM 1022E Pipeline Description
-;; Copyright (C) 2005 Free Software Foundation, Inc.
-;; Contributed by Richard Earnshaw (richard.earnshaw@arm.com)
-;;
-;; This file is part of GCC.
-;;
-;; GCC is free software; you can redistribute it and/or modify it
-;; under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-;;
-;; GCC is distributed in the hope that it will be useful, but
-;; WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-;; General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING. If not, write to the Free
-;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-;; 02110-1301, USA. */
-
-;; These descriptions are based on the information contained in the
-;; ARM1020E Technical Reference Manual, Copyright (c) 2003 ARM
-;; Limited.
-;;
-
-;; This automaton provides a pipeline description for the ARM
-;; 1020E core.
-;;
-;; The model given here assumes that the condition for all conditional
-;; instructions is "true", i.e., that all of the instructions are
-;; actually executed.
-
-(define_automaton "arm1020e")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Pipelines
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; There are two pipelines:
-;;
-;; - An Arithmetic Logic Unit (ALU) pipeline.
-;;
-;; The ALU pipeline has fetch, issue, decode, execute, memory, and
-;; write stages. We only need to model the execute, memory and write
-;; stages.
-;;
-;; - A Load-Store Unit (LSU) pipeline.
-;;
-;; The LSU pipeline has decode, execute, memory, and write stages.
-;; We only model the execute, memory and write stages.
-
-(define_cpu_unit "1020a_e,1020a_m,1020a_w" "arm1020e")
-(define_cpu_unit "1020l_e,1020l_m,1020l_w" "arm1020e")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; ALU Instructions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; ALU instructions require three cycles to execute, and use the ALU
-;; pipeline in each of the three stages. The results are available
-;; after the execute stage stage has finished.
-;;
-;; If the destination register is the PC, the pipelines are stalled
-;; for several cycles. That case is not modeled here.
-
-;; ALU operations with no shifted operand
-(define_insn_reservation "1020alu_op" 1
- (and (eq_attr "tune" "arm1020e,arm1022e")
- (eq_attr "type" "alu"))
- "1020a_e,1020a_m,1020a_w")
-
-;; ALU operations with a shift-by-constant operand
-(define_insn_reservation "1020alu_shift_op" 1
- (and (eq_attr "tune" "arm1020e,arm1022e")
- (eq_attr "type" "alu_shift"))
- "1020a_e,1020a_m,1020a_w")
-
-;; ALU operations with a shift-by-register operand
-;; These really stall in the decoder, in order to read
-;; the shift value in a second cycle. Pretend we take two cycles in
-;; the execute stage.
-(define_insn_reservation "1020alu_shift_reg_op" 2
- (and (eq_attr "tune" "arm1020e,arm1022e")
- (eq_attr "type" "alu_shift_reg"))
- "1020a_e*2,1020a_m,1020a_w")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Multiplication Instructions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; Multiplication instructions loop in the execute stage until the
-;; instruction has been passed through the multiplier array enough
-;; times.
-
-;; The result of the "smul" and "smulw" instructions is not available
-;; until after the memory stage.
-(define_insn_reservation "1020mult1" 2
- (and (eq_attr "tune" "arm1020e,arm1022e")
- (eq_attr "insn" "smulxy,smulwy"))
- "1020a_e,1020a_m,1020a_w")
-
-;; The "smlaxy" and "smlawx" instructions require two iterations through
-;; the execute stage; the result is available immediately following
-;; the execute stage.
-(define_insn_reservation "1020mult2" 2
- (and (eq_attr "tune" "arm1020e,arm1022e")
- (eq_attr "insn" "smlaxy,smlalxy,smlawx"))
- "1020a_e*2,1020a_m,1020a_w")
-
-;; The "smlalxy", "mul", and "mla" instructions require two iterations
-;; through the execute stage; the result is not available until after
-;; the memory stage.
-(define_insn_reservation "1020mult3" 3
- (and (eq_attr "tune" "arm1020e,arm1022e")
- (eq_attr "insn" "smlalxy,mul,mla"))
- "1020a_e*2,1020a_m,1020a_w")
-
-;; The "muls" and "mlas" instructions loop in the execute stage for
-;; four iterations in order to set the flags. The value result is
-;; available after three iterations.
-(define_insn_reservation "1020mult4" 3
- (and (eq_attr "tune" "arm1020e,arm1022e")
- (eq_attr "insn" "muls,mlas"))
- "1020a_e*4,1020a_m,1020a_w")
-
-;; Long multiply instructions that produce two registers of
-;; output (such as umull) make their results available in two cycles;
-;; the least significant word is available before the most significant
-;; word. That fact is not modeled; instead, the instructions are
-;; described.as if the entire result was available at the end of the
-;; cycle in which both words are available.
-
-;; The "umull", "umlal", "smull", and "smlal" instructions all take
-;; three iterations through the execute cycle, and make their results
-;; available after the memory cycle.
-(define_insn_reservation "1020mult5" 4
- (and (eq_attr "tune" "arm1020e,arm1022e")
- (eq_attr "insn" "umull,umlal,smull,smlal"))
- "1020a_e*3,1020a_m,1020a_w")
-
-;; The "umulls", "umlals", "smulls", and "smlals" instructions loop in
-;; the execute stage for five iterations in order to set the flags.
-;; The value result is available after four iterations.
-(define_insn_reservation "1020mult6" 4
- (and (eq_attr "tune" "arm1020e,arm1022e")
- (eq_attr "insn" "umulls,umlals,smulls,smlals"))
- "1020a_e*5,1020a_m,1020a_w")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Load/Store Instructions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; The models for load/store instructions do not accurately describe
-;; the difference between operations with a base register writeback
-;; (such as "ldm!"). These models assume that all memory references
-;; hit in dcache.
-
-;; LSU instructions require six cycles to execute. They use the ALU
-;; pipeline in all but the 5th cycle, and the LSU pipeline in cycles
-;; three through six.
-;; Loads and stores which use a scaled register offset or scaled
-;; register pre-indexed addressing mode take three cycles EXCEPT for
-;; those that are base + offset with LSL of 0 or 2, or base - offset
-;; with LSL of zero. The remainder take 1 cycle to execute.
-;; For 4byte loads there is a bypass from the load stage
-
-(define_insn_reservation "1020load1_op" 2
- (and (eq_attr "tune" "arm1020e,arm1022e")
- (eq_attr "type" "load_byte,load1"))
- "1020a_e+1020l_e,1020l_m,1020l_w")
-
-(define_insn_reservation "1020store1_op" 0
- (and (eq_attr "tune" "arm1020e,arm1022e")
- (eq_attr "type" "store1"))
- "1020a_e+1020l_e,1020l_m,1020l_w")
-
-;; A load's result can be stored by an immediately following store
-(define_bypass 1 "1020load1_op" "1020store1_op" "arm_no_early_store_addr_dep")
-
-;; On a LDM/STM operation, the LSU pipeline iterates until all of the
-;; registers have been processed.
-;;
-;; The time it takes to load the data depends on whether or not the
-;; base address is 64-bit aligned; if it is not, an additional cycle
-;; is required. This model assumes that the address is always 64-bit
-;; aligned. Because the processor can load two registers per cycle,
-;; that assumption means that we use the same instruction reservations
-;; for loading 2k and 2k - 1 registers.
-;;
-;; The ALU pipeline is decoupled after the first cycle unless there is
-;; a register dependency; the dependency is cleared as soon as the LDM/STM
-;; has dealt with the corresponding register. So for example,
-;; stmia sp, {r0-r3}
-;; add r0, r0, #4
-;; will have one fewer stalls than
-;; stmia sp, {r0-r3}
-;; add r3, r3, #4
-;;
-;; As with ALU operations, if one of the destination registers is the
-;; PC, there are additional stalls; that is not modeled.
-
-(define_insn_reservation "1020load2_op" 2
- (and (eq_attr "tune" "arm1020e,arm1022e")
- (eq_attr "type" "load2"))
- "1020a_e+1020l_e,1020l_m,1020l_w")
-
-(define_insn_reservation "1020store2_op" 0
- (and (eq_attr "tune" "arm1020e,arm1022e")
- (eq_attr "type" "store2"))
- "1020a_e+1020l_e,1020l_m,1020l_w")
-
-(define_insn_reservation "1020load34_op" 3
- (and (eq_attr "tune" "arm1020e,arm1022e")
- (eq_attr "type" "load3,load4"))
- "1020a_e+1020l_e,1020l_e+1020l_m,1020l_m,1020l_w")
-
-(define_insn_reservation "1020store34_op" 0
- (and (eq_attr "tune" "arm1020e,arm1022e")
- (eq_attr "type" "store3,store4"))
- "1020a_e+1020l_e,1020l_e+1020l_m,1020l_m,1020l_w")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Branch and Call Instructions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; Branch instructions are difficult to model accurately. The ARM
-;; core can predict most branches. If the branch is predicted
-;; correctly, and predicted early enough, the branch can be completely
-;; eliminated from the instruction stream. Some branches can
-;; therefore appear to require zero cycles to execute. We assume that
-;; all branches are predicted correctly, and that the latency is
-;; therefore the minimum value.
-
-(define_insn_reservation "1020branch_op" 0
- (and (eq_attr "tune" "arm1020e,arm1022e")
- (eq_attr "type" "branch"))
- "1020a_e")
-
-;; The latency for a call is not predictable. Therefore, we use 32 as
-;; roughly equivalent to positive infinity.
-
-(define_insn_reservation "1020call_op" 32
- (and (eq_attr "tune" "arm1020e,arm1022e")
- (eq_attr "type" "call"))
- "1020a_e*32")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; VFP
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(define_cpu_unit "v10_fmac" "arm1020e")
-
-(define_cpu_unit "v10_ds" "arm1020e")
-
-(define_cpu_unit "v10_fmstat" "arm1020e")
-
-(define_cpu_unit "v10_ls1,v10_ls2,v10_ls3" "arm1020e")
-
-;; fmstat is a serializing instruction. It will stall the core until
-;; the mac and ds units have completed.
-(exclusion_set "v10_fmac,v10_ds" "v10_fmstat")
-
-(define_attr "vfp10" "yes,no"
- (const (if_then_else (and (eq_attr "tune" "arm1020e,arm1022e")
- (eq_attr "fpu" "vfp"))
- (const_string "yes") (const_string "no"))))
-
-;; The VFP "type" attributes differ from those used in the FPA model.
-;; ffarith Fast floating point insns, e.g. abs, neg, cpy, cmp.
-;; farith Most arithmetic insns.
-;; fmul Double precision multiply.
-;; fdivs Single precision sqrt or division.
-;; fdivd Double precision sqrt or division.
-;; f_flag fmstat operation
-;; f_load Floating point load from memory.
-;; f_store Floating point store to memory.
-;; f_2_r Transfer vfp to arm reg.
-;; r_2_f Transfer arm to vfp reg.
-
-;; Note, no instruction can issue to the VFP if the core is stalled in the
-;; first execute state. We model this by using 1020a_e in the first cycle.
-(define_insn_reservation "v10_ffarith" 5
- (and (eq_attr "vfp10" "yes")
- (eq_attr "type" "ffarith"))
- "1020a_e+v10_fmac")
-
-(define_insn_reservation "v10_farith" 5
- (and (eq_attr "vfp10" "yes")
- (eq_attr "type" "farith"))
- "1020a_e+v10_fmac")
-
-(define_insn_reservation "v10_cvt" 5
- (and (eq_attr "vfp10" "yes")
- (eq_attr "type" "f_cvt"))
- "1020a_e+v10_fmac")
-
-(define_insn_reservation "v10_fmul" 6
- (and (eq_attr "vfp10" "yes")
- (eq_attr "type" "fmul"))
- "1020a_e+v10_fmac*2")
-
-(define_insn_reservation "v10_fdivs" 18
- (and (eq_attr "vfp10" "yes")
- (eq_attr "type" "fdivs"))
- "1020a_e+v10_ds*14")
-
-(define_insn_reservation "v10_fdivd" 32
- (and (eq_attr "vfp10" "yes")
- (eq_attr "type" "fdivd"))
- "1020a_e+v10_fmac+v10_ds*28")
-
-(define_insn_reservation "v10_floads" 4
- (and (eq_attr "vfp10" "yes")
- (eq_attr "type" "f_loads"))
- "1020a_e+1020l_e+v10_ls1,v10_ls2")
-
-;; We model a load of a double as needing all the vfp ls* stage in cycle 1.
-;; This gives the correct mix between single-and double loads where a flds
-;; followed by and fldd will stall for one cycle, but two back-to-back fldd
-;; insns stall for two cycles.
-(define_insn_reservation "v10_floadd" 5
- (and (eq_attr "vfp10" "yes")
- (eq_attr "type" "f_loadd"))
- "1020a_e+1020l_e+v10_ls1+v10_ls2+v10_ls3,v10_ls2+v10_ls3,v10_ls3")
-
-;; Moves to/from arm regs also use the load/store pipeline.
-
-(define_insn_reservation "v10_c2v" 4
- (and (eq_attr "vfp10" "yes")
- (eq_attr "type" "r_2_f"))
- "1020a_e+1020l_e+v10_ls1,v10_ls2")
-
-(define_insn_reservation "v10_fstores" 1
- (and (eq_attr "vfp10" "yes")
- (eq_attr "type" "f_stores"))
- "1020a_e+1020l_e+v10_ls1,v10_ls2")
-
-(define_insn_reservation "v10_fstored" 1
- (and (eq_attr "vfp10" "yes")
- (eq_attr "type" "f_stored"))
- "1020a_e+1020l_e+v10_ls1+v10_ls2+v10_ls3,v10_ls2+v10_ls3,v10_ls3")
-
-(define_insn_reservation "v10_v2c" 1
- (and (eq_attr "vfp10" "yes")
- (eq_attr "type" "f_2_r"))
- "1020a_e+1020l_e,1020l_m,1020l_w")
-
-(define_insn_reservation "v10_to_cpsr" 2
- (and (eq_attr "vfp10" "yes")
- (eq_attr "type" "f_flag"))
- "1020a_e+v10_fmstat,1020a_e+1020l_e,1020l_m,1020l_w")
-
-;; VFP bypasses
-
-;; There are bypasses for most operations other than store
-
-(define_bypass 3
- "v10_c2v,v10_floads"
- "v10_ffarith,v10_farith,v10_fmul,v10_fdivs,v10_fdivd,v10_cvt")
-
-(define_bypass 4
- "v10_floadd"
- "v10_ffarith,v10_farith,v10_fmul,v10_fdivs,v10_fdivd")
-
-;; Arithmetic to other arithmetic saves a cycle due to forwarding
-(define_bypass 4
- "v10_ffarith,v10_farith"
- "v10_ffarith,v10_farith,v10_fmul,v10_fdivs,v10_fdivd")
-
-(define_bypass 5
- "v10_fmul"
- "v10_ffarith,v10_farith,v10_fmul,v10_fdivs,v10_fdivd")
-
-(define_bypass 17
- "v10_fdivs"
- "v10_ffarith,v10_farith,v10_fmul,v10_fdivs,v10_fdivd")
-
-(define_bypass 31
- "v10_fdivd"
- "v10_ffarith,v10_farith,v10_fmul,v10_fdivs,v10_fdivd")
-
-;; VFP anti-dependencies.
-
-;; There is one anti-dependence in the following case (not yet modelled):
-;; - After a store: one extra cycle for both fsts and fstd
-;; Note, back-to-back fstd instructions will overload the load/store datapath
-;; causing a two-cycle stall.
diff --git a/gcc-4.2.1/gcc/config/arm/arm1026ejs.md b/gcc-4.2.1/gcc/config/arm/arm1026ejs.md
deleted file mode 100644
index a2404ecea..000000000
--- a/gcc-4.2.1/gcc/config/arm/arm1026ejs.md
+++ /dev/null
@@ -1,241 +0,0 @@
-;; ARM 1026EJ-S Pipeline Description
-;; Copyright (C) 2003 Free Software Foundation, Inc.
-;; Written by CodeSourcery, LLC.
-;;
-;; This file is part of GCC.
-;;
-;; GCC is free software; you can redistribute it and/or modify it
-;; under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-;;
-;; GCC is distributed in the hope that it will be useful, but
-;; WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-;; General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING. If not, write to the Free
-;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-;; 02110-1301, USA. */
-
-;; These descriptions are based on the information contained in the
-;; ARM1026EJ-S Technical Reference Manual, Copyright (c) 2003 ARM
-;; Limited.
-;;
-
-;; This automaton provides a pipeline description for the ARM
-;; 1026EJ-S core.
-;;
-;; The model given here assumes that the condition for all conditional
-;; instructions is "true", i.e., that all of the instructions are
-;; actually executed.
-
-(define_automaton "arm1026ejs")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Pipelines
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; There are two pipelines:
-;;
-;; - An Arithmetic Logic Unit (ALU) pipeline.
-;;
-;; The ALU pipeline has fetch, issue, decode, execute, memory, and
-;; write stages. We only need to model the execute, memory and write
-;; stages.
-;;
-;; - A Load-Store Unit (LSU) pipeline.
-;;
-;; The LSU pipeline has decode, execute, memory, and write stages.
-;; We only model the execute, memory and write stages.
-
-(define_cpu_unit "a_e,a_m,a_w" "arm1026ejs")
-(define_cpu_unit "l_e,l_m,l_w" "arm1026ejs")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; ALU Instructions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; ALU instructions require three cycles to execute, and use the ALU
-;; pipeline in each of the three stages. The results are available
-;; after the execute stage stage has finished.
-;;
-;; If the destination register is the PC, the pipelines are stalled
-;; for several cycles. That case is not modeled here.
-
-;; ALU operations with no shifted operand
-(define_insn_reservation "alu_op" 1
- (and (eq_attr "tune" "arm1026ejs")
- (eq_attr "type" "alu"))
- "a_e,a_m,a_w")
-
-;; ALU operations with a shift-by-constant operand
-(define_insn_reservation "alu_shift_op" 1
- (and (eq_attr "tune" "arm1026ejs")
- (eq_attr "type" "alu_shift"))
- "a_e,a_m,a_w")
-
-;; ALU operations with a shift-by-register operand
-;; These really stall in the decoder, in order to read
-;; the shift value in a second cycle. Pretend we take two cycles in
-;; the execute stage.
-(define_insn_reservation "alu_shift_reg_op" 2
- (and (eq_attr "tune" "arm1026ejs")
- (eq_attr "type" "alu_shift_reg"))
- "a_e*2,a_m,a_w")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Multiplication Instructions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; Multiplication instructions loop in the execute stage until the
-;; instruction has been passed through the multiplier array enough
-;; times.
-
-;; The result of the "smul" and "smulw" instructions is not available
-;; until after the memory stage.
-(define_insn_reservation "mult1" 2
- (and (eq_attr "tune" "arm1026ejs")
- (eq_attr "insn" "smulxy,smulwy"))
- "a_e,a_m,a_w")
-
-;; The "smlaxy" and "smlawx" instructions require two iterations through
-;; the execute stage; the result is available immediately following
-;; the execute stage.
-(define_insn_reservation "mult2" 2
- (and (eq_attr "tune" "arm1026ejs")
- (eq_attr "insn" "smlaxy,smlalxy,smlawx"))
- "a_e*2,a_m,a_w")
-
-;; The "smlalxy", "mul", and "mla" instructions require two iterations
-;; through the execute stage; the result is not available until after
-;; the memory stage.
-(define_insn_reservation "mult3" 3
- (and (eq_attr "tune" "arm1026ejs")
- (eq_attr "insn" "smlalxy,mul,mla"))
- "a_e*2,a_m,a_w")
-
-;; The "muls" and "mlas" instructions loop in the execute stage for
-;; four iterations in order to set the flags. The value result is
-;; available after three iterations.
-(define_insn_reservation "mult4" 3
- (and (eq_attr "tune" "arm1026ejs")
- (eq_attr "insn" "muls,mlas"))
- "a_e*4,a_m,a_w")
-
-;; Long multiply instructions that produce two registers of
-;; output (such as umull) make their results available in two cycles;
-;; the least significant word is available before the most significant
-;; word. That fact is not modeled; instead, the instructions are
-;; described.as if the entire result was available at the end of the
-;; cycle in which both words are available.
-
-;; The "umull", "umlal", "smull", and "smlal" instructions all take
-;; three iterations through the execute cycle, and make their results
-;; available after the memory cycle.
-(define_insn_reservation "mult5" 4
- (and (eq_attr "tune" "arm1026ejs")
- (eq_attr "insn" "umull,umlal,smull,smlal"))
- "a_e*3,a_m,a_w")
-
-;; The "umulls", "umlals", "smulls", and "smlals" instructions loop in
-;; the execute stage for five iterations in order to set the flags.
-;; The value result is available after four iterations.
-(define_insn_reservation "mult6" 4
- (and (eq_attr "tune" "arm1026ejs")
- (eq_attr "insn" "umulls,umlals,smulls,smlals"))
- "a_e*5,a_m,a_w")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Load/Store Instructions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; The models for load/store instructions do not accurately describe
-;; the difference between operations with a base register writeback
-;; (such as "ldm!"). These models assume that all memory references
-;; hit in dcache.
-
-;; LSU instructions require six cycles to execute. They use the ALU
-;; pipeline in all but the 5th cycle, and the LSU pipeline in cycles
-;; three through six.
-;; Loads and stores which use a scaled register offset or scaled
-;; register pre-indexed addressing mode take three cycles EXCEPT for
-;; those that are base + offset with LSL of 0 or 2, or base - offset
-;; with LSL of zero. The remainder take 1 cycle to execute.
-;; For 4byte loads there is a bypass from the load stage
-
-(define_insn_reservation "load1_op" 2
- (and (eq_attr "tune" "arm1026ejs")
- (eq_attr "type" "load_byte,load1"))
- "a_e+l_e,l_m,a_w+l_w")
-
-(define_insn_reservation "store1_op" 0
- (and (eq_attr "tune" "arm1026ejs")
- (eq_attr "type" "store1"))
- "a_e+l_e,l_m,a_w+l_w")
-
-;; A load's result can be stored by an immediately following store
-(define_bypass 1 "load1_op" "store1_op" "arm_no_early_store_addr_dep")
-
-;; On a LDM/STM operation, the LSU pipeline iterates until all of the
-;; registers have been processed.
-;;
-;; The time it takes to load the data depends on whether or not the
-;; base address is 64-bit aligned; if it is not, an additional cycle
-;; is required. This model assumes that the address is always 64-bit
-;; aligned. Because the processor can load two registers per cycle,
-;; that assumption means that we use the same instruction reservations
-;; for loading 2k and 2k - 1 registers.
-;;
-;; The ALU pipeline is stalled until the completion of the last memory
-;; stage in the LSU pipeline. That is modeled by keeping the ALU
-;; execute stage busy until that point.
-;;
-;; As with ALU operations, if one of the destination registers is the
-;; PC, there are additional stalls; that is not modeled.
-
-(define_insn_reservation "load2_op" 2
- (and (eq_attr "tune" "arm1026ejs")
- (eq_attr "type" "load2"))
- "a_e+l_e,l_m,a_w+l_w")
-
-(define_insn_reservation "store2_op" 0
- (and (eq_attr "tune" "arm1026ejs")
- (eq_attr "type" "store2"))
- "a_e+l_e,l_m,a_w+l_w")
-
-(define_insn_reservation "load34_op" 3
- (and (eq_attr "tune" "arm1026ejs")
- (eq_attr "type" "load3,load4"))
- "a_e+l_e,a_e+l_e+l_m,a_e+l_m,a_w+l_w")
-
-(define_insn_reservation "store34_op" 0
- (and (eq_attr "tune" "arm1026ejs")
- (eq_attr "type" "store3,store4"))
- "a_e+l_e,a_e+l_e+l_m,a_e+l_m,a_w+l_w")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Branch and Call Instructions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; Branch instructions are difficult to model accurately. The ARM
-;; core can predict most branches. If the branch is predicted
-;; correctly, and predicted early enough, the branch can be completely
-;; eliminated from the instruction stream. Some branches can
-;; therefore appear to require zero cycles to execute. We assume that
-;; all branches are predicted correctly, and that the latency is
-;; therefore the minimum value.
-
-(define_insn_reservation "branch_op" 0
- (and (eq_attr "tune" "arm1026ejs")
- (eq_attr "type" "branch"))
- "nothing")
-
-;; The latency for a call is not predictable. Therefore, we use 32 as
-;; roughly equivalent to positive infinity.
-
-(define_insn_reservation "call_op" 32
- (and (eq_attr "tune" "arm1026ejs")
- (eq_attr "type" "call"))
- "nothing")
diff --git a/gcc-4.2.1/gcc/config/arm/arm1136jfs.md b/gcc-4.2.1/gcc/config/arm/arm1136jfs.md
deleted file mode 100644
index 308669750..000000000
--- a/gcc-4.2.1/gcc/config/arm/arm1136jfs.md
+++ /dev/null
@@ -1,377 +0,0 @@
-;; ARM 1136J[F]-S Pipeline Description
-;; Copyright (C) 2003 Free Software Foundation, Inc.
-;; Written by CodeSourcery, LLC.
-;;
-;; This file is part of GCC.
-;;
-;; GCC is free software; you can redistribute it and/or modify it
-;; under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-;;
-;; GCC is distributed in the hope that it will be useful, but
-;; WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-;; General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING. If not, write to the Free
-;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-;; 02110-1301, USA. */
-
-;; These descriptions are based on the information contained in the
-;; ARM1136JF-S Technical Reference Manual, Copyright (c) 2003 ARM
-;; Limited.
-;;
-
-;; This automaton provides a pipeline description for the ARM
-;; 1136J-S and 1136JF-S cores.
-;;
-;; The model given here assumes that the condition for all conditional
-;; instructions is "true", i.e., that all of the instructions are
-;; actually executed.
-
-(define_automaton "arm1136jfs")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Pipelines
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; There are three distinct pipelines (page 1-26 and following):
-;;
-;; - A 4-stage decode pipeline, shared by all three. It has fetch (1),
-;; fetch (2), decode, and issue stages. Since this is always involved,
-;; we do not model it in the scheduler.
-;;
-;; - A 4-stage ALU pipeline. It has shifter, ALU (main integer operations),
-;; and saturation stages. The fourth stage is writeback; see below.
-;;
-;; - A 4-stage multiply-accumulate pipeline. It has three stages, called
-;; MAC1 through MAC3, and a fourth writeback stage.
-;;
-;; The 4th-stage writeback is shared between the ALU and MAC pipelines,
-;; which operate in lockstep. Results from either pipeline will be
-;; moved into the writeback stage. Because the two pipelines operate
-;; in lockstep, we schedule them as a single "execute" pipeline.
-;;
-;; - A 4-stage LSU pipeline. It has address generation, data cache (1),
-;; data cache (2), and writeback stages. (Note that this pipeline,
-;; including the writeback stage, is independent from the ALU & LSU pipes.)
-
-(define_cpu_unit "e_1,e_2,e_3,e_wb" "arm1136jfs") ; ALU and MAC
-; e_1 = Sh/Mac1, e_2 = ALU/Mac2, e_3 = SAT/Mac3
-(define_cpu_unit "l_a,l_dc1,l_dc2,l_wb" "arm1136jfs") ; Load/Store
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; ALU Instructions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; ALU instructions require eight cycles to execute, and use the ALU
-;; pipeline in each of the eight stages. The results are available
-;; after the alu stage has finished.
-;;
-;; If the destination register is the PC, the pipelines are stalled
-;; for several cycles. That case is not modelled here.
-
-;; ALU operations with no shifted operand
-(define_insn_reservation "11_alu_op" 2
- (and (eq_attr "tune" "arm1136js,arm1136jfs")
- (eq_attr "type" "alu"))
- "e_1,e_2,e_3,e_wb")
-
-;; ALU operations with a shift-by-constant operand
-(define_insn_reservation "11_alu_shift_op" 2
- (and (eq_attr "tune" "arm1136js,arm1136jfs")
- (eq_attr "type" "alu_shift"))
- "e_1,e_2,e_3,e_wb")
-
-;; ALU operations with a shift-by-register operand
-;; These really stall in the decoder, in order to read
-;; the shift value in a second cycle. Pretend we take two cycles in
-;; the shift stage.
-(define_insn_reservation "11_alu_shift_reg_op" 3
- (and (eq_attr "tune" "arm1136js,arm1136jfs")
- (eq_attr "type" "alu_shift_reg"))
- "e_1*2,e_2,e_3,e_wb")
-
-;; alu_ops can start sooner, if there is no shifter dependency
-(define_bypass 1 "11_alu_op,11_alu_shift_op"
- "11_alu_op")
-(define_bypass 1 "11_alu_op,11_alu_shift_op"
- "11_alu_shift_op"
- "arm_no_early_alu_shift_value_dep")
-(define_bypass 1 "11_alu_op,11_alu_shift_op"
- "11_alu_shift_reg_op"
- "arm_no_early_alu_shift_dep")
-(define_bypass 2 "11_alu_shift_reg_op"
- "11_alu_op")
-(define_bypass 2 "11_alu_shift_reg_op"
- "11_alu_shift_op"
- "arm_no_early_alu_shift_value_dep")
-(define_bypass 2 "11_alu_shift_reg_op"
- "11_alu_shift_reg_op"
- "arm_no_early_alu_shift_dep")
-
-(define_bypass 1 "11_alu_op,11_alu_shift_op"
- "11_mult1,11_mult2,11_mult3,11_mult4,11_mult5,11_mult6,11_mult7"
- "arm_no_early_mul_dep")
-(define_bypass 2 "11_alu_shift_reg_op"
- "11_mult1,11_mult2,11_mult3,11_mult4,11_mult5,11_mult6,11_mult7"
- "arm_no_early_mul_dep")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Multiplication Instructions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; Multiplication instructions loop in the first two execute stages until
-;; the instruction has been passed through the multiplier array enough
-;; times.
-
-;; Multiply and multiply-accumulate results are available after four stages.
-(define_insn_reservation "11_mult1" 4
- (and (eq_attr "tune" "arm1136js,arm1136jfs")
- (eq_attr "insn" "mul,mla"))
- "e_1*2,e_2,e_3,e_wb")
-
-;; The *S variants set the condition flags, which requires three more cycles.
-(define_insn_reservation "11_mult2" 4
- (and (eq_attr "tune" "arm1136js,arm1136jfs")
- (eq_attr "insn" "muls,mlas"))
- "e_1*2,e_2,e_3,e_wb")
-
-(define_bypass 3 "11_mult1,11_mult2"
- "11_mult1,11_mult2,11_mult3,11_mult4,11_mult5,11_mult6,11_mult7"
- "arm_no_early_mul_dep")
-(define_bypass 3 "11_mult1,11_mult2"
- "11_alu_op")
-(define_bypass 3 "11_mult1,11_mult2"
- "11_alu_shift_op"
- "arm_no_early_alu_shift_value_dep")
-(define_bypass 3 "11_mult1,11_mult2"
- "11_alu_shift_reg_op"
- "arm_no_early_alu_shift_dep")
-(define_bypass 3 "11_mult1,11_mult2"
- "11_store1"
- "arm_no_early_store_addr_dep")
-
-;; Signed and unsigned multiply long results are available across two cycles;
-;; the less significant word is available one cycle before the more significant
-;; word. Here we conservatively wait until both are available, which is
-;; after three iterations and the memory cycle. The same is also true of
-;; the two multiply-accumulate instructions.
-(define_insn_reservation "11_mult3" 5
- (and (eq_attr "tune" "arm1136js,arm1136jfs")
- (eq_attr "insn" "smull,umull,smlal,umlal"))
- "e_1*3,e_2,e_3,e_wb*2")
-
-;; The *S variants set the condition flags, which requires three more cycles.
-(define_insn_reservation "11_mult4" 5
- (and (eq_attr "tune" "arm1136js,arm1136jfs")
- (eq_attr "insn" "smulls,umulls,smlals,umlals"))
- "e_1*3,e_2,e_3,e_wb*2")
-
-(define_bypass 4 "11_mult3,11_mult4"
- "11_mult1,11_mult2,11_mult3,11_mult4,11_mult5,11_mult6,11_mult7"
- "arm_no_early_mul_dep")
-(define_bypass 4 "11_mult3,11_mult4"
- "11_alu_op")
-(define_bypass 4 "11_mult3,11_mult4"
- "11_alu_shift_op"
- "arm_no_early_alu_shift_value_dep")
-(define_bypass 4 "11_mult3,11_mult4"
- "11_alu_shift_reg_op"
- "arm_no_early_alu_shift_dep")
-(define_bypass 4 "11_mult3,11_mult4"
- "11_store1"
- "arm_no_early_store_addr_dep")
-
-;; Various 16x16->32 multiplies and multiply-accumulates, using combinations
-;; of high and low halves of the argument registers. They take a single
-;; pass through the pipeline and make the result available after three
-;; cycles.
-(define_insn_reservation "11_mult5" 3
- (and (eq_attr "tune" "arm1136js,arm1136jfs")
- (eq_attr "insn" "smulxy,smlaxy,smulwy,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx"))
- "e_1,e_2,e_3,e_wb")
-
-(define_bypass 2 "11_mult5"
- "11_mult1,11_mult2,11_mult3,11_mult4,11_mult5,11_mult6,11_mult7"
- "arm_no_early_mul_dep")
-(define_bypass 2 "11_mult5"
- "11_alu_op")
-(define_bypass 2 "11_mult5"
- "11_alu_shift_op"
- "arm_no_early_alu_shift_value_dep")
-(define_bypass 2 "11_mult5"
- "11_alu_shift_reg_op"
- "arm_no_early_alu_shift_dep")
-(define_bypass 2 "11_mult5"
- "11_store1"
- "arm_no_early_store_addr_dep")
-
-;; The same idea, then the 32-bit result is added to a 64-bit quantity.
-(define_insn_reservation "11_mult6" 4
- (and (eq_attr "tune" "arm1136js,arm1136jfs")
- (eq_attr "insn" "smlalxy"))
- "e_1*2,e_2,e_3,e_wb*2")
-
-;; Signed 32x32 multiply, then the most significant 32 bits are extracted
-;; and are available after the memory stage.
-(define_insn_reservation "11_mult7" 4
- (and (eq_attr "tune" "arm1136js,arm1136jfs")
- (eq_attr "insn" "smmul,smmulr"))
- "e_1*2,e_2,e_3,e_wb")
-
-(define_bypass 3 "11_mult6,11_mult7"
- "11_mult1,11_mult2,11_mult3,11_mult4,11_mult5,11_mult6,11_mult7"
- "arm_no_early_mul_dep")
-(define_bypass 3 "11_mult6,11_mult7"
- "11_alu_op")
-(define_bypass 3 "11_mult6,11_mult7"
- "11_alu_shift_op"
- "arm_no_early_alu_shift_value_dep")
-(define_bypass 3 "11_mult6,11_mult7"
- "11_alu_shift_reg_op"
- "arm_no_early_alu_shift_dep")
-(define_bypass 3 "11_mult6,11_mult7"
- "11_store1"
- "arm_no_early_store_addr_dep")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Branch Instructions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; These vary greatly depending on their arguments and the results of
-;; stat prediction. Cycle count ranges from zero (unconditional branch,
-;; folded dynamic prediction) to seven (incorrect predictions, etc). We
-;; assume an optimal case for now, because the cost of a cache miss
-;; overwhelms the cost of everything else anyhow.
-
-(define_insn_reservation "11_branches" 0
- (and (eq_attr "tune" "arm1136js,arm1136jfs")
- (eq_attr "type" "branch"))
- "nothing")
-
-;; Call latencies are not predictable. A semi-arbitrary very large
-;; number is used as "positive infinity" so that everything should be
-;; finished by the time of return.
-(define_insn_reservation "11_call" 32
- (and (eq_attr "tune" "arm1136js,arm1136jfs")
- (eq_attr "type" "call"))
- "nothing")
-
-;; Branches are predicted. A correctly predicted branch will be no
-;; cost, but we're conservative here, and use the timings a
-;; late-register would give us.
-(define_bypass 1 "11_alu_op,11_alu_shift_op"
- "11_branches")
-(define_bypass 2 "11_alu_shift_reg_op"
- "11_branches")
-(define_bypass 2 "11_load1,11_load2"
- "11_branches")
-(define_bypass 3 "11_load34"
- "11_branches")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Load/Store Instructions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; The models for load/store instructions do not accurately describe
-;; the difference between operations with a base register writeback.
-;; These models assume that all memory references hit in dcache. Also,
-;; if the PC is one of the registers involved, there are additional stalls
-;; not modelled here. Addressing modes are also not modelled.
-
-(define_insn_reservation "11_load1" 3
- (and (eq_attr "tune" "arm1136js,arm1136jfs")
- (eq_attr "type" "load1"))
- "l_a+e_1,l_dc1,l_dc2,l_wb")
-
-;; Load byte results are not available until the writeback stage, where
-;; the correct byte is extracted.
-
-(define_insn_reservation "11_loadb" 4
- (and (eq_attr "tune" "arm1136js,arm1136jfs")
- (eq_attr "type" "load_byte"))
- "l_a+e_1,l_dc1,l_dc2,l_wb")
-
-(define_insn_reservation "11_store1" 0
- (and (eq_attr "tune" "arm1136js,arm1136jfs")
- (eq_attr "type" "store1"))
- "l_a+e_1,l_dc1,l_dc2,l_wb")
-
-;; Load/store double words into adjacent registers. The timing and
-;; latencies are different depending on whether the address is 64-bit
-;; aligned. This model assumes that it is.
-(define_insn_reservation "11_load2" 3
- (and (eq_attr "tune" "arm1136js,arm1136jfs")
- (eq_attr "type" "load2"))
- "l_a+e_1,l_dc1,l_dc2,l_wb")
-
-(define_insn_reservation "11_store2" 0
- (and (eq_attr "tune" "arm1136js,arm1136jfs")
- (eq_attr "type" "store2"))
- "l_a+e_1,l_dc1,l_dc2,l_wb")
-
-;; Load/store multiple registers. Two registers are stored per cycle.
-;; Actual timing depends on how many registers are affected, so we
-;; optimistically schedule a low latency.
-(define_insn_reservation "11_load34" 4
- (and (eq_attr "tune" "arm1136js,arm1136jfs")
- (eq_attr "type" "load3,load4"))
- "l_a+e_1,l_dc1*2,l_dc2,l_wb")
-
-(define_insn_reservation "11_store34" 0
- (and (eq_attr "tune" "arm1136js,arm1136jfs")
- (eq_attr "type" "store3,store4"))
- "l_a+e_1,l_dc1*2,l_dc2,l_wb")
-
-;; A store can start immediately after an alu op, if that alu op does
-;; not provide part of the address to access.
-(define_bypass 1 "11_alu_op,11_alu_shift_op"
- "11_store1"
- "arm_no_early_store_addr_dep")
-(define_bypass 2 "11_alu_shift_reg_op"
- "11_store1"
- "arm_no_early_store_addr_dep")
-
-;; An alu op can start sooner after a load, if that alu op does not
-;; have an early register dependency on the load
-(define_bypass 2 "11_load1"
- "11_alu_op")
-(define_bypass 2 "11_load1"
- "11_alu_shift_op"
- "arm_no_early_alu_shift_value_dep")
-(define_bypass 2 "11_load1"
- "11_alu_shift_reg_op"
- "arm_no_early_alu_shift_dep")
-
-(define_bypass 3 "11_loadb"
- "11_alu_op")
-(define_bypass 3 "11_loadb"
- "11_alu_shift_op"
- "arm_no_early_alu_shift_value_dep")
-(define_bypass 3 "11_loadb"
- "11_alu_shift_reg_op"
- "arm_no_early_alu_shift_dep")
-
-;; A mul op can start sooner after a load, if that mul op does not
-;; have an early multiply dependency
-(define_bypass 2 "11_load1"
- "11_mult1,11_mult2,11_mult3,11_mult4,11_mult5,11_mult6,11_mult7"
- "arm_no_early_mul_dep")
-(define_bypass 3 "11_load34"
- "11_mult1,11_mult2,11_mult3,11_mult4,11_mult5,11_mult6,11_mult7"
- "arm_no_early_mul_dep")
-(define_bypass 3 "11_loadb"
- "11_mult1,11_mult2,11_mult3,11_mult4,11_mult5,11_mult6,11_mult7"
- "arm_no_early_mul_dep")
-
-;; A store can start sooner after a load, if that load does not
-;; produce part of the address to access
-(define_bypass 2 "11_load1"
- "11_store1"
- "arm_no_early_store_addr_dep")
-(define_bypass 3 "11_loadb"
- "11_store1"
- "arm_no_early_store_addr_dep")
diff --git a/gcc-4.2.1/gcc/config/arm/arm926ejs.md b/gcc-4.2.1/gcc/config/arm/arm926ejs.md
deleted file mode 100644
index 244e3a91c..000000000
--- a/gcc-4.2.1/gcc/config/arm/arm926ejs.md
+++ /dev/null
@@ -1,188 +0,0 @@
-;; ARM 926EJ-S Pipeline Description
-;; Copyright (C) 2003 Free Software Foundation, Inc.
-;; Written by CodeSourcery, LLC.
-;;
-;; This file is part of GCC.
-;;
-;; GCC is free software; you can redistribute it and/or modify it
-;; under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-;;
-;; GCC is distributed in the hope that it will be useful, but
-;; WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-;; General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING. If not, write to the Free
-;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-;; 02110-1301, USA. */
-
-;; These descriptions are based on the information contained in the
-;; ARM926EJ-S Technical Reference Manual, Copyright (c) 2002 ARM
-;; Limited.
-;;
-
-;; This automaton provides a pipeline description for the ARM
-;; 926EJ-S core.
-;;
-;; The model given here assumes that the condition for all conditional
-;; instructions is "true", i.e., that all of the instructions are
-;; actually executed.
-
-(define_automaton "arm926ejs")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Pipelines
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; There is a single pipeline
-;;
-;; The ALU pipeline has fetch, decode, execute, memory, and
-;; write stages. We only need to model the execute, memory and write
-;; stages.
-
-(define_cpu_unit "e,m,w" "arm926ejs")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; ALU Instructions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; ALU instructions require three cycles to execute, and use the ALU
-;; pipeline in each of the three stages. The results are available
-;; after the execute stage stage has finished.
-;;
-;; If the destination register is the PC, the pipelines are stalled
-;; for several cycles. That case is not modeled here.
-
-;; ALU operations with no shifted operand
-(define_insn_reservation "9_alu_op" 1
- (and (eq_attr "tune" "arm926ejs")
- (eq_attr "type" "alu,alu_shift"))
- "e,m,w")
-
-;; ALU operations with a shift-by-register operand
-;; These really stall in the decoder, in order to read
-;; the shift value in a second cycle. Pretend we take two cycles in
-;; the execute stage.
-(define_insn_reservation "9_alu_shift_reg_op" 2
- (and (eq_attr "tune" "arm926ejs")
- (eq_attr "type" "alu_shift_reg"))
- "e*2,m,w")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Multiplication Instructions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; Multiplication instructions loop in the execute stage until the
-;; instruction has been passed through the multiplier array enough
-;; times. Multiply operations occur in both the execute and memory
-;; stages of the pipeline
-
-(define_insn_reservation "9_mult1" 3
- (and (eq_attr "tune" "arm926ejs")
- (eq_attr "insn" "smlalxy,mul,mla"))
- "e*2,m,w")
-
-(define_insn_reservation "9_mult2" 4
- (and (eq_attr "tune" "arm926ejs")
- (eq_attr "insn" "muls,mlas"))
- "e*3,m,w")
-
-(define_insn_reservation "9_mult3" 4
- (and (eq_attr "tune" "arm926ejs")
- (eq_attr "insn" "umull,umlal,smull,smlal"))
- "e*3,m,w")
-
-(define_insn_reservation "9_mult4" 5
- (and (eq_attr "tune" "arm926ejs")
- (eq_attr "insn" "umulls,umlals,smulls,smlals"))
- "e*4,m,w")
-
-(define_insn_reservation "9_mult5" 2
- (and (eq_attr "tune" "arm926ejs")
- (eq_attr "insn" "smulxy,smlaxy,smlawx"))
- "e,m,w")
-
-(define_insn_reservation "9_mult6" 3
- (and (eq_attr "tune" "arm926ejs")
- (eq_attr "insn" "smlalxy"))
- "e*2,m,w")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Load/Store Instructions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; The models for load/store instructions do not accurately describe
-;; the difference between operations with a base register writeback
-;; (such as "ldm!"). These models assume that all memory references
-;; hit in dcache.
-
-;; Loads with a shifted offset take 3 cycles, and are (a) probably the
-;; most common and (b) the pessimistic assumption will lead to fewer stalls.
-(define_insn_reservation "9_load1_op" 3
- (and (eq_attr "tune" "arm926ejs")
- (eq_attr "type" "load1,load_byte"))
- "e*2,m,w")
-
-(define_insn_reservation "9_store1_op" 0
- (and (eq_attr "tune" "arm926ejs")
- (eq_attr "type" "store1"))
- "e,m,w")
-
-;; multiple word loads and stores
-(define_insn_reservation "9_load2_op" 3
- (and (eq_attr "tune" "arm926ejs")
- (eq_attr "type" "load2"))
- "e,m*2,w")
-
-(define_insn_reservation "9_load3_op" 4
- (and (eq_attr "tune" "arm926ejs")
- (eq_attr "type" "load3"))
- "e,m*3,w")
-
-(define_insn_reservation "9_load4_op" 5
- (and (eq_attr "tune" "arm926ejs")
- (eq_attr "type" "load4"))
- "e,m*4,w")
-
-(define_insn_reservation "9_store2_op" 0
- (and (eq_attr "tune" "arm926ejs")
- (eq_attr "type" "store2"))
- "e,m*2,w")
-
-(define_insn_reservation "9_store3_op" 0
- (and (eq_attr "tune" "arm926ejs")
- (eq_attr "type" "store3"))
- "e,m*3,w")
-
-(define_insn_reservation "9_store4_op" 0
- (and (eq_attr "tune" "arm926ejs")
- (eq_attr "type" "store4"))
- "e,m*4,w")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Branch and Call Instructions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; Branch instructions are difficult to model accurately. The ARM
-;; core can predict most branches. If the branch is predicted
-;; correctly, and predicted early enough, the branch can be completely
-;; eliminated from the instruction stream. Some branches can
-;; therefore appear to require zero cycles to execute. We assume that
-;; all branches are predicted correctly, and that the latency is
-;; therefore the minimum value.
-
-(define_insn_reservation "9_branch_op" 0
- (and (eq_attr "tune" "arm926ejs")
- (eq_attr "type" "branch"))
- "nothing")
-
-;; The latency for a call is not predictable. Therefore, we use 32 as
-;; roughly equivalent to positive infinity.
-
-(define_insn_reservation "9_call_op" 32
- (and (eq_attr "tune" "arm926ejs")
- (eq_attr "type" "call"))
- "nothing")
diff --git a/gcc-4.2.1/gcc/config/arm/bpabi.S b/gcc-4.2.1/gcc/config/arm/bpabi.S
deleted file mode 100644
index e492d4be6..000000000
--- a/gcc-4.2.1/gcc/config/arm/bpabi.S
+++ /dev/null
@@ -1,95 +0,0 @@
-/* Miscellaneous BPABI functions.
-
- Copyright (C) 2003, 2004 Free Software Foundation, Inc.
- Contributed by CodeSourcery, LLC.
-
- 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 into combinations with other programs,
- and to distribute those combinations 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 a combine
- executable.)
-
- 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, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-#ifdef __ARMEB__
-#define xxh r0
-#define xxl r1
-#define yyh r2
-#define yyl r3
-#else
-#define xxh r1
-#define xxl r0
-#define yyh r3
-#define yyl r2
-#endif
-
-#ifdef L_aeabi_lcmp
-
-ARM_FUNC_START aeabi_lcmp
- subs ip, xxl, yyl
- sbcs ip, xxh, yyh
- subeqs ip, xxl, yyl
- mov r0, ip
- RET
- FUNC_END aeabi_lcmp
-
-#endif /* L_aeabi_lcmp */
-
-#ifdef L_aeabi_ulcmp
-
-ARM_FUNC_START aeabi_ulcmp
- cmp xxh, yyh
- movlo r0, #-1
- movhi r0, #1
- RETc(ne)
- cmp xxl, yyl
- movlo r0, #-1
- movhi r0, #1
- moveq r0, #0
- RET
- FUNC_END aeabi_ulcmp
-
-#endif /* L_aeabi_ulcmp */
-
-#ifdef L_aeabi_ldivmod
-
-ARM_FUNC_START aeabi_ldivmod
- sub sp, sp, #8
- stmfd sp!, {sp, lr}
- bl SYM(__gnu_ldivmod_helper) __PLT__
- ldr lr, [sp, #4]
- add sp, sp, #8
- ldmfd sp!, {r2, r3}
- RET
-
-#endif /* L_aeabi_ldivmod */
-
-#ifdef L_aeabi_uldivmod
-
-ARM_FUNC_START aeabi_uldivmod
- sub sp, sp, #8
- stmfd sp!, {sp, lr}
- bl SYM(__gnu_uldivmod_helper) __PLT__
- ldr lr, [sp, #4]
- add sp, sp, #8
- ldmfd sp!, {r2, r3}
- RET
-
-#endif /* L_aeabi_divmod */
-
diff --git a/gcc-4.2.1/gcc/config/arm/bpabi.c b/gcc-4.2.1/gcc/config/arm/bpabi.c
deleted file mode 100644
index 69f6e4ede..000000000
--- a/gcc-4.2.1/gcc/config/arm/bpabi.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Miscellaneous BPABI functions.
-
- Copyright (C) 2003, 2004 Free Software Foundation, Inc.
- Contributed by CodeSourcery, LLC.
-
- 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 into combinations with other programs,
- and to distribute those combinations 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 a combine
- executable.)
-
- 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, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-extern long long __divdi3 (long long, long long);
-extern unsigned long long __udivdi3 (unsigned long long,
- unsigned long long);
-extern long long __gnu_ldivmod_helper (long long, long long, long long *);
-extern unsigned long long __gnu_uldivmod_helper (unsigned long long,
- unsigned long long,
- unsigned long long *);
-
-
-long long
-__gnu_ldivmod_helper (long long a,
- long long b,
- long long *remainder)
-{
- long long quotient;
-
- quotient = __divdi3 (a, b);
- *remainder = a - b * quotient;
- return quotient;
-}
-
-unsigned long long
-__gnu_uldivmod_helper (unsigned long long a,
- unsigned long long b,
- unsigned long long *remainder)
-{
- unsigned long long quotient;
-
- quotient = __udivdi3 (a, b);
- *remainder = a - b * quotient;
- return quotient;
-}
diff --git a/gcc-4.2.1/gcc/config/arm/bpabi.h b/gcc-4.2.1/gcc/config/arm/bpabi.h
deleted file mode 100644
index a4287292f..000000000
--- a/gcc-4.2.1/gcc/config/arm/bpabi.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/* Configuration file for ARM BPABI targets.
- Copyright (C) 2004, 2005
- Free Software Foundation, Inc.
- Contributed by CodeSourcery, LLC
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* Use the AAPCS ABI by default. */
-#define ARM_DEFAULT_ABI ARM_ABI_AAPCS
-
-/* Assume that AAPCS ABIs should adhere to the full BPABI. */
-#define TARGET_BPABI (TARGET_AAPCS_BASED)
-
-/* BPABI targets use EABI frame unwinding tables. */
-#define TARGET_UNWIND_INFO 1
-
-/* Section 4.1 of the AAPCS requires the use of VFP format. */
-#undef FPUTYPE_DEFAULT
-#define FPUTYPE_DEFAULT FPUTYPE_VFP
-
-/* EABI targets should enable interworking by default. */
-#undef TARGET_DEFAULT
-#define TARGET_DEFAULT MASK_INTERWORK
-
-/* The ARM BPABI functions return a boolean; they use no special
- calling convention. */
-#define FLOAT_LIB_COMPARE_RETURNS_BOOL(MODE, COMPARISON) TARGET_BPABI
-
-/* The BPABI integer comparison routines return { -1, 0, 1 }. */
-#define TARGET_LIB_INT_CMP_BIASED !TARGET_BPABI
-
-/* Tell the assembler to build BPABI binaries. */
-#undef SUBTARGET_EXTRA_ASM_SPEC
-#define SUBTARGET_EXTRA_ASM_SPEC "%{mabi=apcs-gnu|mabi=atpcs:-meabi=gnu;:-meabi=4}"
-
-/* The generic link spec in elf.h does not support shared libraries. */
-#define BPABI_LINK_SPEC \
- "%{mbig-endian:-EB} %{mlittle-endian:-EL} " \
- "%{static:-Bstatic} %{shared:-shared} %{symbolic:-Bsymbolic} " \
- "-X"
-
-#undef LINK_SPEC
-#define LINK_SPEC BPABI_LINK_SPEC
-
-#if defined (__thumb__)
-#define RENAME_LIBRARY_SET ".thumb_set"
-#else
-#define RENAME_LIBRARY_SET ".set"
-#endif
-
-/* Make __aeabi_AEABI_NAME an alias for __GCC_NAME. */
-#define RENAME_LIBRARY(GCC_NAME, AEABI_NAME) \
- __asm__ (".globl\t__aeabi_" #AEABI_NAME "\n" \
- RENAME_LIBRARY_SET "\t__aeabi_" #AEABI_NAME \
- ", __" #GCC_NAME "\n");
-
-/* Give some libgcc functions an additional __aeabi name. */
-#ifdef L_muldi3
-#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (muldi3, lmul)
-#endif
-#ifdef L_muldi3
-#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (muldi3, lmul)
-#endif
-#ifdef L_fixdfdi
-#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixdfdi, d2lz)
-#endif
-#ifdef L_fixunsdfdi
-#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixunsdfdi, d2ulz)
-#endif
-#ifdef L_fixsfdi
-#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixsfdi, f2lz)
-#endif
-#ifdef L_fixunssfdi
-#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixunssfdi, f2ulz)
-#endif
-#ifdef L_floatdidf
-#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (floatdidf, l2d)
-#endif
-#ifdef L_floatdisf
-#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (floatdisf, l2f)
-#endif
-
-/* The BPABI requires that we always use an out-of-line implementation
- of RTTI comparison, even if the target supports weak symbols,
- because the same object file might be used on a target that does
- not support merging symbols across DLL boundaries. This macro is
- broken out separately so that it can be used within
- TARGET_OS_CPP_BUILTINS in configuration files for systems based on
- the BPABI. */
-#define TARGET_BPABI_CPP_BUILTINS() \
- do \
- { \
- builtin_define ("__GXX_MERGED_TYPEINFO_NAMES=0"); \
- } \
- while (false)
-
-#undef TARGET_OS_CPP_BUILTINS
-#define TARGET_OS_CPP_BUILTINS() \
- TARGET_BPABI_CPP_BUILTINS()
-
-/* The BPABI specifies the use of .{init,fini}_array. Therefore, we
- do not want GCC to put anything into the .{init,fini} sections. */
-#undef INIT_SECTION_ASM_OP
-#undef FINI_SECTION_ASM_OP
-#define INIT_ARRAY_SECTION_ASM_OP ARM_EABI_CTORS_SECTION_OP
-#define FINI_ARRAY_SECTION_ASM_OP ARM_EABI_DTORS_SECTION_OP
diff --git a/gcc-4.2.1/gcc/config/arm/cirrus.md b/gcc-4.2.1/gcc/config/arm/cirrus.md
deleted file mode 100644
index 052198906..000000000
--- a/gcc-4.2.1/gcc/config/arm/cirrus.md
+++ /dev/null
@@ -1,458 +0,0 @@
-;; Cirrus EP9312 "Maverick" ARM floating point co-processor description.
-;; Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
-;; Contributed by Red Hat.
-;; Written by Aldy Hernandez (aldyh@redhat.com)
-
-;; This file is part of GCC.
-
-;; GCC is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GCC is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
-
-
-; Cirrus types for invalid insn combinations
-; not Not a cirrus insn
-; normal Any Cirrus insn not covered by the special cases below
-; double cfldrd, cfldr64, cfstrd, cfstr64
-; compare cfcmps, cfcmpd, cfcmp32, cfcmp64
-; move cfmvdlr, cfmvdhr, cfmvsr, cfmv64lr, cfmv64hr
-(define_attr "cirrus" "not,normal,double,compare,move" (const_string "not"))
-
-
-(define_insn "cirrus_adddi3"
- [(set (match_operand:DI 0 "cirrus_fp_register" "=v")
- (plus:DI (match_operand:DI 1 "cirrus_fp_register" "v")
- (match_operand:DI 2 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cfadd64%?\\t%V0, %V1, %V2"
- [(set_attr "type" "mav_farith")
- (set_attr "cirrus" "normal")]
-)
-
-(define_insn "*cirrus_addsi3"
- [(set (match_operand:SI 0 "cirrus_fp_register" "=v")
- (plus:SI (match_operand:SI 1 "cirrus_fp_register" "v")
- (match_operand:SI 2 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK && 0"
- "cfadd32%?\\t%V0, %V1, %V2"
- [(set_attr "type" "mav_farith")
- (set_attr "cirrus" "normal")]
-)
-
-(define_insn "*cirrus_addsf3"
- [(set (match_operand:SF 0 "cirrus_fp_register" "=v")
- (plus:SF (match_operand:SF 1 "cirrus_fp_register" "v")
- (match_operand:SF 2 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cfadds%?\\t%V0, %V1, %V2"
- [(set_attr "type" "mav_farith")
- (set_attr "cirrus" "normal")]
-)
-
-(define_insn "*cirrus_adddf3"
- [(set (match_operand:DF 0 "cirrus_fp_register" "=v")
- (plus:DF (match_operand:DF 1 "cirrus_fp_register" "v")
- (match_operand:DF 2 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cfaddd%?\\t%V0, %V1, %V2"
- [(set_attr "type" "mav_farith")
- (set_attr "cirrus" "normal")]
-)
-
-(define_insn "cirrus_subdi3"
- [(set (match_operand:DI 0 "cirrus_fp_register" "=v")
- (minus:DI (match_operand:DI 1 "cirrus_fp_register" "v")
- (match_operand:DI 2 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cfsub64%?\\t%V0, %V1, %V2"
- [(set_attr "type" "mav_farith")
- (set_attr "cirrus" "normal")]
-)
-
-(define_insn "*cirrus_subsi3_insn"
- [(set (match_operand:SI 0 "cirrus_fp_register" "=v")
- (minus:SI (match_operand:SI 1 "cirrus_fp_register" "v")
- (match_operand:SI 2 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK && 0"
- "cfsub32%?\\t%V0, %V1, %V2"
- [(set_attr "type" "mav_farith")
- (set_attr "cirrus" "normal")]
-)
-
-(define_insn "*cirrus_subsf3"
- [(set (match_operand:SF 0 "cirrus_fp_register" "=v")
- (minus:SF (match_operand:SF 1 "cirrus_fp_register" "v")
- (match_operand:SF 2 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cfsubs%?\\t%V0, %V1, %V2"
- [(set_attr "type" "mav_farith")
- (set_attr "cirrus" "normal")]
-)
-
-(define_insn "*cirrus_subdf3"
- [(set (match_operand:DF 0 "cirrus_fp_register" "=v")
- (minus:DF (match_operand:DF 1 "cirrus_fp_register" "v")
- (match_operand:DF 2 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cfsubd%?\\t%V0, %V1, %V2"
- [(set_attr "type" "mav_farith")
- (set_attr "cirrus" "normal")]
-)
-
-(define_insn "*cirrus_mulsi3"
- [(set (match_operand:SI 0 "cirrus_fp_register" "=v")
- (mult:SI (match_operand:SI 2 "cirrus_fp_register" "v")
- (match_operand:SI 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK && 0"
- "cfmul32%?\\t%V0, %V1, %V2"
- [(set_attr "type" "mav_farith")
- (set_attr "cirrus" "normal")]
-)
-
-(define_insn "muldi3"
- [(set (match_operand:DI 0 "cirrus_fp_register" "=v")
- (mult:DI (match_operand:DI 2 "cirrus_fp_register" "v")
- (match_operand:DI 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cfmul64%?\\t%V0, %V1, %V2"
- [(set_attr "type" "mav_dmult")
- (set_attr "cirrus" "normal")]
-)
-
-(define_insn "*cirrus_mulsi3addsi"
- [(set (match_operand:SI 0 "cirrus_fp_register" "=v")
- (plus:SI
- (mult:SI (match_operand:SI 1 "cirrus_fp_register" "v")
- (match_operand:SI 2 "cirrus_fp_register" "v"))
- (match_operand:SI 3 "cirrus_fp_register" "0")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK && 0"
- "cfmac32%?\\t%V0, %V1, %V2"
- [(set_attr "type" "mav_farith")
- (set_attr "cirrus" "normal")]
-)
-
-;; Cirrus SI multiply-subtract
-(define_insn "*cirrus_mulsi3subsi"
- [(set (match_operand:SI 0 "cirrus_fp_register" "=v")
- (minus:SI
- (match_operand:SI 1 "cirrus_fp_register" "0")
- (mult:SI (match_operand:SI 2 "cirrus_fp_register" "v")
- (match_operand:SI 3 "cirrus_fp_register" "v"))))]
- "0 && TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cfmsc32%?\\t%V0, %V2, %V3"
- [(set_attr "type" "mav_farith")
- (set_attr "cirrus" "normal")]
-)
-
-(define_insn "*cirrus_mulsf3"
- [(set (match_operand:SF 0 "cirrus_fp_register" "=v")
- (mult:SF (match_operand:SF 1 "cirrus_fp_register" "v")
- (match_operand:SF 2 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cfmuls%?\\t%V0, %V1, %V2"
- [(set_attr "type" "mav_farith")
- (set_attr "cirrus" "normal")]
-)
-
-(define_insn "*cirrus_muldf3"
- [(set (match_operand:DF 0 "cirrus_fp_register" "=v")
- (mult:DF (match_operand:DF 1 "cirrus_fp_register" "v")
- (match_operand:DF 2 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cfmuld%?\\t%V0, %V1, %V2"
- [(set_attr "type" "mav_dmult")
- (set_attr "cirrus" "normal")]
-)
-
-(define_insn "cirrus_ashl_const"
- [(set (match_operand:SI 0 "cirrus_fp_register" "=v")
- (ashift:SI (match_operand:SI 1 "cirrus_fp_register" "v")
- (match_operand:SI 2 "cirrus_shift_const" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK && 0"
- "cfsh32%?\\t%V0, %V1, #%s2"
- [(set_attr "cirrus" "normal")]
-)
-
-(define_insn "cirrus_ashiftrt_const"
- [(set (match_operand:SI 0 "cirrus_fp_register" "=v")
- (ashiftrt:SI (match_operand:SI 1 "cirrus_fp_register" "v")
- (match_operand:SI 2 "cirrus_shift_const" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK && 0"
- "cfsh32%?\\t%V0, %V1, #-%s2"
- [(set_attr "cirrus" "normal")]
-)
-
-(define_insn "cirrus_ashlsi3"
- [(set (match_operand:SI 0 "cirrus_fp_register" "=v")
- (ashift:SI (match_operand:SI 1 "cirrus_fp_register" "v")
- (match_operand:SI 2 "register_operand" "r")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK && 0"
- "cfrshl32%?\\t%V1, %V0, %s2"
- [(set_attr "cirrus" "normal")]
-)
-
-(define_insn "ashldi3_cirrus"
- [(set (match_operand:DI 0 "cirrus_fp_register" "=v")
- (ashift:DI (match_operand:DI 1 "cirrus_fp_register" "v")
- (match_operand:SI 2 "register_operand" "r")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cfrshl64%?\\t%V1, %V0, %s2"
- [(set_attr "cirrus" "normal")]
-)
-
-(define_insn "cirrus_ashldi_const"
- [(set (match_operand:DI 0 "cirrus_fp_register" "=v")
- (ashift:DI (match_operand:DI 1 "cirrus_fp_register" "v")
- (match_operand:SI 2 "cirrus_shift_const" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cfsh64%?\\t%V0, %V1, #%s2"
- [(set_attr "cirrus" "normal")]
-)
-
-(define_insn "cirrus_ashiftrtdi_const"
- [(set (match_operand:DI 0 "cirrus_fp_register" "=v")
- (ashiftrt:DI (match_operand:DI 1 "cirrus_fp_register" "v")
- (match_operand:SI 2 "cirrus_shift_const" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cfsh64%?\\t%V0, %V1, #-%s2"
- [(set_attr "cirrus" "normal")]
-)
-
-(define_insn "*cirrus_absdi2"
- [(set (match_operand:DI 0 "cirrus_fp_register" "=v")
- (abs:DI (match_operand:DI 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cfabs64%?\\t%V0, %V1"
- [(set_attr "cirrus" "normal")]
-)
-
-;; This doesn't really clobber ``cc''. Fixme: aldyh.
-(define_insn "*cirrus_negdi2"
- [(set (match_operand:DI 0 "cirrus_fp_register" "=v")
- (neg:DI (match_operand:DI 1 "cirrus_fp_register" "v")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cfneg64%?\\t%V0, %V1"
- [(set_attr "cirrus" "normal")]
-)
-
-(define_insn "*cirrus_negsi2"
- [(set (match_operand:SI 0 "cirrus_fp_register" "=v")
- (neg:SI (match_operand:SI 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK && 0"
- "cfneg32%?\\t%V0, %V1"
- [(set_attr "cirrus" "normal")]
-)
-
-(define_insn "*cirrus_negsf2"
- [(set (match_operand:SF 0 "cirrus_fp_register" "=v")
- (neg:SF (match_operand:SF 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cfnegs%?\\t%V0, %V1"
- [(set_attr "cirrus" "normal")]
-)
-
-(define_insn "*cirrus_negdf2"
- [(set (match_operand:DF 0 "cirrus_fp_register" "=v")
- (neg:DF (match_operand:DF 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cfnegd%?\\t%V0, %V1"
- [(set_attr "cirrus" "normal")]
-)
-
-;; This doesn't really clobber the condition codes either.
-(define_insn "*cirrus_abssi2"
- [(set (match_operand:SI 0 "cirrus_fp_register" "=v")
- (abs:SI (match_operand:SI 1 "cirrus_fp_register" "v")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK && 0"
- "cfabs32%?\\t%V0, %V1"
- [(set_attr "cirrus" "normal")]
-)
-
-(define_insn "*cirrus_abssf2"
- [(set (match_operand:SF 0 "cirrus_fp_register" "=v")
- (abs:SF (match_operand:SF 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cfabss%?\\t%V0, %V1"
- [(set_attr "cirrus" "normal")]
-)
-
-(define_insn "*cirrus_absdf2"
- [(set (match_operand:DF 0 "cirrus_fp_register" "=v")
- (abs:DF (match_operand:DF 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cfabsd%?\\t%V0, %V1"
- [(set_attr "cirrus" "normal")]
-)
-
-;; Convert Cirrus-SI to Cirrus-SF
-(define_insn "cirrus_floatsisf2"
- [(set (match_operand:SF 0 "cirrus_fp_register" "=v")
- (float:SF (match_operand:SI 1 "s_register_operand" "r")))
- (clobber (match_scratch:DF 2 "=v"))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cfmv64lr%?\\t%Z2, %1\;cfcvt32s%?\\t%V0, %Y2"
- [(set_attr "length" "8")
- (set_attr "cirrus" "move")]
-)
-
-(define_insn "cirrus_floatsidf2"
- [(set (match_operand:DF 0 "cirrus_fp_register" "=v")
- (float:DF (match_operand:SI 1 "s_register_operand" "r")))
- (clobber (match_scratch:DF 2 "=v"))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cfmv64lr%?\\t%Z2, %1\;cfcvt32d%?\\t%V0, %Y2"
- [(set_attr "length" "8")
- (set_attr "cirrus" "move")]
-)
-
-(define_insn "floatdisf2"
- [(set (match_operand:SF 0 "cirrus_fp_register" "=v")
- (float:SF (match_operand:DI 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cfcvt64s%?\\t%V0, %V1"
- [(set_attr "cirrus" "normal")])
-
-(define_insn "floatdidf2"
- [(set (match_operand:DF 0 "cirrus_fp_register" "=v")
- (float:DF (match_operand:DI 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cfcvt64d%?\\t%V0, %V1"
- [(set_attr "cirrus" "normal")])
-
-(define_insn "cirrus_truncsfsi2"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (fix:SI (fix:SF (match_operand:SF 1 "cirrus_fp_register" "v"))))
- (clobber (match_scratch:DF 2 "=v"))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cftruncs32%?\\t%Y2, %V1\;cfmvr64l%?\\t%0, %Z2"
- [(set_attr "length" "8")
- (set_attr "cirrus" "normal")]
-)
-
-(define_insn "cirrus_truncdfsi2"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (fix:SI (fix:DF (match_operand:DF 1 "cirrus_fp_register" "v"))))
- (clobber (match_scratch:DF 2 "=v"))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cftruncd32%?\\t%Y2, %V1\;cfmvr64l%?\\t%0, %Z2"
- [(set_attr "length" "8")]
-)
-
-(define_insn "*cirrus_truncdfsf2"
- [(set (match_operand:SF 0 "cirrus_fp_register" "=v")
- (float_truncate:SF
- (match_operand:DF 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cfcvtds%?\\t%V0, %V1"
- [(set_attr "cirrus" "normal")]
-)
-
-(define_insn "*cirrus_extendsfdf2"
- [(set (match_operand:DF 0 "cirrus_fp_register" "=v")
- (float_extend:DF (match_operand:SF 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "cfcvtsd%?\\t%V0, %V1"
- [(set_attr "cirrus" "normal")]
-)
-
-(define_insn "*cirrus_arm_movdi"
- [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r,r,o<>,v,r,v,m,v")
- (match_operand:DI 1 "di_operand" "rIK,mi,r,r,v,mi,v,v"))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "*
- {
- switch (which_alternative)
- {
- case 0:
- return \"#\";
- case 1:
- case 2:
- return output_move_double (operands);
-
- case 3: return \"cfmv64lr%?\\t%V0, %Q1\;cfmv64hr%?\\t%V0, %R1\";
- case 4: return \"cfmvr64l%?\\t%Q0, %V1\;cfmvr64h%?\\t%R0, %V1\";
-
- case 5: return \"cfldr64%?\\t%V0, %1\";
- case 6: return \"cfstr64%?\\t%V1, %0\";
-
- /* Shifting by 0 will just copy %1 into %0. */
- case 7: return \"cfsh64%?\\t%V0, %V1, #0\";
-
- default: gcc_unreachable ();
- }
- }"
- [(set_attr "length" " 8, 8, 8, 8, 8, 4, 4, 4")
- (set_attr "type" " *,load2,store2, *, *, load2,store2, *")
- (set_attr "pool_range" " *,1020, *, *, *, 1020, *, *")
- (set_attr "neg_pool_range" " *,1012, *, *, *, 1008, *, *")
- (set_attr "cirrus" "not, not, not,move,normal,double,double,normal")]
-)
-
-;; Cirrus SI values have been outlawed. Look in arm.h for the comment
-;; on HARD_REGNO_MODE_OK.
-
-(define_insn "*cirrus_movsf_hard_insn"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=v,v,v,r,m,r,r,m")
- (match_operand:SF 1 "general_operand" "v,mE,r,v,v,r,mE,r"))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK
- && (GET_CODE (operands[0]) != MEM
- || register_operand (operands[1], SFmode))"
- "@
- cfcpys%?\\t%V0, %V1
- cfldrs%?\\t%V0, %1
- cfmvsr%?\\t%V0, %1
- cfmvrs%?\\t%0, %V1
- cfstrs%?\\t%V1, %0
- mov%?\\t%0, %1
- ldr%?\\t%0, %1\\t%@ float
- str%?\\t%1, %0\\t%@ float"
- [(set_attr "length" " *, *, *, *, *, 4, 4, 4")
- (set_attr "type" " *, load1, *, *,store1, *,load1,store1")
- (set_attr "pool_range" " *, 1020, *, *, *, *,4096, *")
- (set_attr "neg_pool_range" " *, 1008, *, *, *, *,4084, *")
- (set_attr "cirrus" "normal,normal,move,normal,normal,not, not, not")]
-)
-
-(define_insn "*cirrus_movdf_hard_insn"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=r,Q,r,m,r,v,v,v,r,m")
- (match_operand:DF 1 "general_operand" "Q,r,r,r,mF,v,mF,r,v,v"))]
- "TARGET_ARM
- && TARGET_HARD_FLOAT && TARGET_MAVERICK
- && (GET_CODE (operands[0]) != MEM
- || register_operand (operands[1], DFmode))"
- "*
- {
- switch (which_alternative)
- {
- case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
- case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
- case 2: return \"#\";
- case 3: case 4: return output_move_double (operands);
- case 5: return \"cfcpyd%?\\t%V0, %V1\";
- case 6: return \"cfldrd%?\\t%V0, %1\";
- case 7: return \"cfmvdlr\\t%V0, %Q1\;cfmvdhr%?\\t%V0, %R1\";
- case 8: return \"cfmvrdl%?\\t%Q0, %V1\;cfmvrdh%?\\t%R0, %V1\";
- case 9: return \"cfstrd%?\\t%V1, %0\";
- default: gcc_unreachable ();
- }
- }"
- [(set_attr "type" "load1,store2, *,store2,load1, *, load1, *, *,store2")
- (set_attr "length" " 4, 4, 8, 8, 8, 4, 4, 8, 8, 4")
- (set_attr "pool_range" " *, *, *, *, 252, *, 1020, *, *, *")
- (set_attr "neg_pool_range" " *, *, *, *, 244, *, 1008, *, *, *")
- (set_attr "cirrus" " not, not,not, not, not,normal,double,move,normal,double")]
-)
-
diff --git a/gcc-4.2.1/gcc/config/arm/coff.h b/gcc-4.2.1/gcc/config/arm/coff.h
deleted file mode 100644
index f4ad4162e..000000000
--- a/gcc-4.2.1/gcc/config/arm/coff.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* Definitions of target machine for GNU compiler.
- For ARM with COFF object format.
- Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005
- Free Software Foundation, Inc.
- Contributed by Doug Evans (devans@cygnus.com).
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* Note - it is important that this definition matches the one in tcoff.h. */
-#undef USER_LABEL_PREFIX
-#define USER_LABEL_PREFIX "_"
-
-
-/* Run-time Target Specification. */
-#undef TARGET_VERSION
-#define TARGET_VERSION fputs (" (ARM/coff)", stderr)
-
-#undef TARGET_DEFAULT_FLOAT_ABI
-#define TARGET_DEFAULT_FLOAT_ABI ARM_FLOAT_ABI_SOFT
-
-#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_APCS_FRAME)
-
-#ifndef MULTILIB_DEFAULTS
-#define MULTILIB_DEFAULTS \
- { "marm", "mlittle-endian", "msoft-float", "mno-thumb-interwork" }
-#endif
-
-/* This is COFF, but prefer stabs. */
-#define SDB_DEBUGGING_INFO 1
-
-#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
-
-
-#define TARGET_ASM_FILE_START_APP_OFF true
-
-/* Switch into a generic section. */
-#define TARGET_ASM_NAMED_SECTION default_coff_asm_named_section
-
-/* Support the ctors/dtors and other sections. */
-
-#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. */
-/* We put ARM jump tables in the text section, because it makes the code
- more efficient, but for Thumb it's better to put them out of band. */
-#define JUMP_TABLES_IN_TEXT_SECTION (TARGET_ARM)
-
-#undef READONLY_DATA_SECTION_ASM_OP
-#define READONLY_DATA_SECTION_ASM_OP "\t.section .rdata"
-#undef CTORS_SECTION_ASM_OP
-#define CTORS_SECTION_ASM_OP "\t.section .ctors,\"x\""
-#undef DTORS_SECTION_ASM_OP
-#define DTORS_SECTION_ASM_OP "\t.section .dtors,\"x\""
-
-/* Support the ctors/dtors sections for g++. */
-
-/* __CTOR_LIST__ and __DTOR_LIST__ must be defined by the linker script. */
-#define CTOR_LISTS_DEFINED_EXTERNALLY
-
-#undef DO_GLOBAL_CTORS_BODY
-#undef DO_GLOBAL_DTORS_BODY
-
-/* The ARM development system defines __main. */
-#define NAME__MAIN "__gccmain"
-#define SYMBOL__MAIN __gccmain
-
-#define SUPPORTS_INIT_PRIORITY 0
diff --git a/gcc-4.2.1/gcc/config/arm/constraints.md b/gcc-4.2.1/gcc/config/arm/constraints.md
deleted file mode 100644
index 790b7de4a..000000000
--- a/gcc-4.2.1/gcc/config/arm/constraints.md
+++ /dev/null
@@ -1,186 +0,0 @@
-;; Constraint definitions for ARM and Thumb
-;; Copyright (C) 2006 Free Software Foundation, Inc.
-;; Contributed by ARM Ltd.
-
-;; This file is part of GCC.
-
-;; GCC is free software; you can redistribute it and/or modify it
-;; under the terms of the GNU General Public License as published
-;; by the Free Software Foundation; either version 2, or (at your
-;; option) any later version.
-
-;; GCC is distributed in the hope that it will be useful, but WITHOUT
-;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
-;; License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
-
-;; The following register constraints have been used:
-;; - in ARM state: f, v, w, y, z
-;; - in Thumb state: h, k, b
-;; - in both states: l, c
-;; In ARM state, 'l' is an alias for 'r'
-
-;; The following normal constraints have been used:
-;; in ARM state: G, H, I, J, K, L, M
-;; in Thumb state: I, J, K, L, M, N, O
-
-;; The following multi-letter normal constraints have been used:
-;; in ARM state: Da, Db, Dc
-
-;; The following memory constraints have been used:
-;; in ARM state: Q, Uq, Uv, Uy
-
-
-(define_register_constraint "f" "TARGET_ARM ? FPA_REGS : NO_REGS"
- "Legacy FPA registers @code{f0}-@code{f7}.")
-
-(define_register_constraint "v" "TARGET_ARM ? CIRRUS_REGS : NO_REGS"
- "The Cirrus Maverick co-processor registers.")
-
-(define_register_constraint "w" "TARGET_ARM ? VFP_REGS : NO_REGS"
- "The VFP registers @code{s0}-@code{s31}.")
-
-(define_register_constraint "y" "TARGET_REALLY_IWMMXT ? IWMMXT_REGS : NO_REGS"
- "The Intel iWMMX co-processor registers.")
-
-(define_register_constraint "z"
- "TARGET_REALLY_IWMMXT ? IWMMXT_GR_REGS : NO_REGS"
- "The Intel iWMMX GR registers.")
-
-(define_register_constraint "l" "TARGET_THUMB ? LO_REGS : GENERAL_REGS"
- "In Thumb state the core registers @code{r0}-@code{r7}.")
-
-(define_register_constraint "h" "TARGET_THUMB ? HI_REGS : NO_REGS"
- "In Thumb state the core registers @code{r8}-@code{r15}.")
-
-(define_register_constraint "k" "TARGET_THUMB ? STACK_REG : NO_REGS"
- "@internal
- Thumb only. The stack register.")
-
-(define_register_constraint "b" "TARGET_THUMB ? BASE_REGS : NO_REGS"
- "@internal
- Thumb only. The union of the low registers and the stack register.")
-
-(define_register_constraint "c" "CC_REG"
- "@internal The condition code register.")
-
-(define_constraint "I"
- "In ARM state a constant that can be used as an immediate value in a Data
- Processing instruction. In Thumb state a constant in the range 0-255."
- (and (match_code "const_int")
- (match_test "TARGET_ARM ? const_ok_for_arm (ival)
- : ival >= 0 && ival <= 255")))
-
-(define_constraint "J"
- "In ARM state a constant in the range @minus{}4095-4095. In Thumb state
- a constant in the range @minus{}255-@minus{}1."
- (and (match_code "const_int")
- (match_test "TARGET_ARM ? (ival >= -4095 && ival <= 4095)
- : (ival >= -255 && ival <= -1)")))
-
-(define_constraint "K"
- "In ARM state a constant that satisfies the @code{I} constraint if inverted.
- In Thumb state a constant that satisfies the @code{I} constraint multiplied
- by any power of 2."
- (and (match_code "const_int")
- (match_test "TARGET_ARM ? const_ok_for_arm (~ival)
- : thumb_shiftable_const (ival)")))
-
-(define_constraint "L"
- "In ARM state a constant that satisfies the @code{I} constraint if negated.
- In Thumb state a constant in the range @minus{}7-7."
- (and (match_code "const_int")
- (match_test "TARGET_ARM ? const_ok_for_arm (-ival)
- : (ival >= -7 && ival <= 7)")))
-
-;; The ARM state version is internal...
-;; @internal In ARM state a constant in the range 0-32 or any power of 2.
-(define_constraint "M"
- "In Thumb state a constant that is a multiple of 4 in the range 0-1020."
- (and (match_code "const_int")
- (match_test "TARGET_ARM ? ((ival >= 0 && ival <= 32)
- || ((ival & (ival - 1)) == 0))
- : ((ival >= 0 && ival <= 1020) && ((ival & 3) == 0))")))
-
-(define_constraint "N"
- "In Thumb state a constant in the range 0-31."
- (and (match_code "const_int")
- (match_test "TARGET_THUMB && ival >= 0 && ival <= 31")))
-
-(define_constraint "O"
- "In Thumb state a constant that is a multiple of 4 in the range
- @minus{}508-508."
- (and (match_code "const_int")
- (match_test "TARGET_THUMB && ival >= -508 && ival <= 508
- && ((ival & 3) == 0)")))
-
-(define_constraint "G"
- "In ARM state a valid FPA immediate constant."
- (and (match_code "const_double")
- (match_test "TARGET_ARM && arm_const_double_rtx (op)")))
-
-(define_constraint "H"
- "In ARM state a valid FPA immediate constant when negated."
- (and (match_code "const_double")
- (match_test "TARGET_ARM && neg_const_double_rtx_ok_for_fpa (op)")))
-
-(define_constraint "Da"
- "@internal
- In ARM state a const_int, const_double or const_vector that can
- be generated with two Data Processing insns."
- (and (match_code "const_double,const_int,const_vector")
- (match_test "TARGET_ARM && arm_const_double_inline_cost (op) == 2")))
-
-(define_constraint "Db"
- "@internal
- In ARM state a const_int, const_double or const_vector that can
- be generated with three Data Processing insns."
- (and (match_code "const_double,const_int,const_vector")
- (match_test "TARGET_ARM && arm_const_double_inline_cost (op) == 3")))
-
-(define_constraint "Dc"
- "@internal
- In ARM state a const_int, const_double or const_vector that can
- be generated with four Data Processing insns. This pattern is disabled
- if optimizing for space or when we have load-delay slots to fill."
- (and (match_code "const_double,const_int,const_vector")
- (match_test "TARGET_ARM && arm_const_double_inline_cost (op) == 4
- && !(optimize_size || arm_ld_sched)")))
-
-(define_memory_constraint "Uv"
- "@internal
- In ARM state a valid VFP load/store address."
- (and (match_code "mem")
- (match_test "TARGET_ARM && arm_coproc_mem_operand (op, FALSE)")))
-
-(define_memory_constraint "Uy"
- "@internal
- In ARM state a valid iWMMX load/store address."
- (and (match_code "mem")
- (match_test "TARGET_ARM && arm_coproc_mem_operand (op, TRUE)")))
-
-(define_memory_constraint "Uq"
- "@internal
- In ARM state an address valid in ldrsb instructions."
- (and (match_code "mem")
- (match_test "TARGET_ARM
- && arm_legitimate_address_p (GET_MODE (op), XEXP (op, 0),
- SIGN_EXTEND, 0)")))
-
-(define_memory_constraint "Q"
- "@internal
- In ARM state an address that is a single base register."
- (and (match_code "mem")
- (match_test "REG_P (XEXP (op, 0))")))
-
-;; We used to have constraint letters for S and R in ARM state, but
-;; all uses of these now appear to have been removed.
-
-;; Additionally, we used to have a Q constraint in Thumb state, but
-;; this wasn't really a valid memory constraint. Again, all uses of
-;; this now seem to have been removed.
diff --git a/gcc-4.2.1/gcc/config/arm/crti.asm b/gcc-4.2.1/gcc/config/arm/crti.asm
deleted file mode 100644
index abacdd1e3..000000000
--- a/gcc-4.2.1/gcc/config/arm/crti.asm
+++ /dev/null
@@ -1,89 +0,0 @@
-# Copyright (C) 2001 Free Software Foundation, Inc.
-# Written By Nick Clifton
-#
-# 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, 51 Franklin Street, Fifth Floor,
-# Boston, MA 02110-1301, USA.
-#
-# As a special exception, if you link this library with files
-# compiled with GCC to produce an executable, this does not 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.
-#
-/* An executable stack is *not* required for these functions. */
-#if defined(__ELF__) && defined(__linux__)
-.section .note.GNU-stack,"",%progbits
-.previous
-#endif
-
-# This file just make a stack frame for the contents of the .fini and
-# .init sections. Users may put any desired instructions in those
-# sections.
-
-#ifdef __ELF__
-#define TYPE(x) .type x,function
-#else
-#define TYPE(x)
-#endif
-
- # Note - this macro is complemented by the FUNC_END macro
- # in crtn.asm. If you change this macro you must also change
- # that macro match.
-.macro FUNC_START
-#ifdef __thumb__
- .thumb
-
- push {r3, r4, r5, r6, r7, lr}
-#else
- .arm
- # Create a stack frame and save any call-preserved registers
- mov ip, sp
- stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, lr, pc}
- sub fp, ip, #4
-#endif
-.endm
-
- .file "crti.asm"
-
- .section ".init"
- .align 2
- .global _init
-#ifdef __thumb__
- .thumb_func
-#endif
- TYPE(_init)
-_init:
- FUNC_START
-
-
- .section ".fini"
- .align 2
- .global _fini
-#ifdef __thumb__
- .thumb_func
-#endif
- TYPE(_fini)
-_fini:
- FUNC_START
-
-# end of crti.asm
diff --git a/gcc-4.2.1/gcc/config/arm/crtn.asm b/gcc-4.2.1/gcc/config/arm/crtn.asm
deleted file mode 100644
index 84facb933..000000000
--- a/gcc-4.2.1/gcc/config/arm/crtn.asm
+++ /dev/null
@@ -1,84 +0,0 @@
-# Copyright (C) 2001, 2004 Free Software Foundation, Inc.
-# Written By Nick Clifton
-#
-# 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, 51 Franklin Street, Fifth Floor,
-# Boston, MA 02110-1301, USA.
-#
-# As a special exception, if you link this library with files
-# compiled with GCC to produce an executable, this does not 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.
-#
-/* An executable stack is *not* required for these functions. */
-#if defined(__ELF__) && defined(__linux__)
-.section .note.GNU-stack,"",%progbits
-.previous
-#endif
-
-# This file just makes sure that the .fini and .init sections do in
-# fact return. Users may put any desired instructions in those sections.
-# This file is the last thing linked into any executable.
-
- # Note - this macro is complemented by the FUNC_START macro
- # in crti.asm. If you change this macro you must also change
- # that macro match.
- #
- # Note - we do not try any fancy optimizations of the return
- # sequences here, it is just not worth it. Instead keep things
- # simple. Restore all the save resgisters, including the link
- # register and then perform the correct function return instruction.
- # We also save/restore r3 to ensure stack alignment.
-.macro FUNC_END
-#ifdef __thumb__
- .thumb
-
- pop {r3, r4, r5, r6, r7}
- pop {r3}
- mov lr, r3
-#else
- .arm
-
- sub sp, fp, #40
- ldmfd sp, {r4, r5, r6, r7, r8, r9, sl, fp, sp, lr}
-#endif
-
-#if defined __THUMB_INTERWORK__ || defined __thumb__
- bx lr
-#else
- mov pc, lr
-#endif
-.endm
-
-
- .file "crtn.asm"
-
- .section ".init"
- ;;
- FUNC_END
-
- .section ".fini"
- ;;
- FUNC_END
-
-# end of crtn.asm
diff --git a/gcc-4.2.1/gcc/config/arm/eabi.h b/gcc-4.2.1/gcc/config/arm/eabi.h
deleted file mode 100644
index afe81556c..000000000
--- a/gcc-4.2.1/gcc/config/arm/eabi.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/* Configuration file for ARM EABI targets.
- Copyright (C) 2008
- Free Software Foundation, Inc.
- Contributed by Doug Kwan (dougkwan@google.com)
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
-
-/* This file contains macro overrides for EABI targets. */
-
-#undef TARGET_OS_CPP_BUILTINS
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- TARGET_BPABI_CPP_BUILTINS (); \
- if (TARGET_ANDROID) \
- builtin_define ("__ANDROID__"); \
- } \
- while (false)
-
-#undef SUBSUBTARGET_EXTRA_SPECS
-#define SUBSUBTARGET_EXTRA_SPECS \
- { "link_android", ANDROID_LINK_SPEC }, \
- { "link_default", BPABI_LINK_SPEC }, \
- { "cc1_android", ANDROID_CC1_SPEC }, \
- { "cc1_default", CC1_DEFAULT_SPEC }, \
- { "cc1plus_android", ANDROID_CC1PLUS_SPEC }, \
- { "cc1plus_default", CC1PLUS_DEFAULT_SPEC }, \
- { "lib_android", ANDROID_LIB_SPEC }, \
- { "lib_default", LIB_DEFAULT_SPEC }, \
- { "startfile_android", ANDROID_STARTFILE_SPEC }, \
- { "startfile_default", UNKNOWN_ELF_STARTFILE_SPEC }, \
- { "endfile_android", ANDROID_ENDFILE_SPEC }, \
- { "endfile_default", UNKNOWN_ELF_ENDFILE_SPEC }, \
-
-#undef ANDROID_LINK_SPEC
-#define ANDROID_LINK_SPEC \
-"%{mbig-endian:-EB} %{mlittle-endian:-EL} " \
-"%{static:-Bstatic} %{shared:-shared} %{symbolic:-Bsymbolic} " \
-"%{!static:" \
- "%{shared: -Bsymbolic} " \
- "%{!shared:" \
- "-Bdynamic " \
- "%{rdynamic:-export-dynamic} " \
- "%{!dynamic-linker:-dynamic-linker /system/bin/linker}}} " \
-"-X"
-
-/* Override LINK_SPEC in bpabi.h. */
-#undef LINK_SPEC
-#define LINK_SPEC \
-"%{mandroid: %(link_android) ;" \
-" : %(link_default)}"
-
-/* Android uses "-fno-exceptions -fpic -fno-short-enums -mthumb-interwork" by
- default. */
-#undef ANDROID_CC1_SPEC
-#define ANDROID_CC1_SPEC \
-"%{!fexceptions:-fno-exceptions} " \
-"%{!fno-pic:%{!fno-PIC:-fpic}} " \
-"%{!fshort-enums:-fno-short-enums} " \
-"%{!mno-thumb-interwork:-mthumb-interwork}"
-
-/* Default CC1_SPEC as in arm.h. */
-#undef CC1_DEFAULT_SPEC
-#define CC1_DEFAULT_SPEC ""
-
-#undef CC1_SPEC
-#define CC1_SPEC \
-"%{mandroid: %(cc1_android) ;" \
-" : %(cc1_default)}"
-
-/* Android uses -fno-rtti by default. */
-#undef ANDROID_CC1PLUS_SPEC
-#define ANDROID_CC1PLUS_SPEC "%{!frtti:-fno-rtti}"
-
-/* Default CC1PLUS_SPEC as in gcc.c. */
-#undef CC1PLUS_DEFAULT_SPEC
-#define CC1PLUS_DEFAULT_SPEC ""
-
-#undef CC1PLUS_SPEC
-#define CC1PLUS_SPEC \
-"%{mandroid: %(cc1plus_android) ;" \
-" : %(cc1plus_default)}"
-
-#undef ANDROID_LIB_SPEC
-#define ANDROID_LIB_SPEC "-lc %{!static:-ldl}"
-
-/* Default LIB_SPEC as in gcc.c. */
-#undef LIB_DEFAULT_SPEC
-#define LIB_DEFAULT_SPEC \
-"%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
-
-#undef LIB_SPEC
-#define LIB_SPEC \
-"%{mandroid: %(lib_android) ;" \
-" : %(lib_default)}"
-
-#undef ANDROID_STARTFILE_SPEC
-#define ANDROID_STARTFILE_SPEC \
-"%{!shared:" \
- "%{static: crtbegin_static%O%s ;" \
- " : crtbegin_dynamic%O%s}}"
-
-/* Override STARTFILE_SPEC in unknown-elf.h. */
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC \
-"%{mandroid: %(startfile_android) ;" \
-" : %(startfile_default)}"
-
-#undef ANDROID_ENDFILE_SPEC
-#define ANDROID_ENDFILE_SPEC "%{!shared:crtend_android%O%s}"
-
-/* Override ENDFILE_SPEC in unknown-elf.h. */
-#undef ENDFILE_SPEC
-#define ENDFILE_SPEC \
-"%{mandroid: %(endfile_android) ;" \
-" : %(endfile_default)}"
-
-/* Add .note.GNU-stack. */
-#undef NEED_INDICATE_EXEC_STACK
-#define NEED_INDICATE_EXEC_STACK 1
diff --git a/gcc-4.2.1/gcc/config/arm/eabi.opt b/gcc-4.2.1/gcc/config/arm/eabi.opt
deleted file mode 100644
index 0ea58bd6e..000000000
--- a/gcc-4.2.1/gcc/config/arm/eabi.opt
+++ /dev/null
@@ -1,23 +0,0 @@
-; EABI specific options for ARM port of the compiler.
-
-; Copyright (C) 2008 Free Software Foundation, Inc.
-;
-; This file is part of GCC.
-;
-; GCC is free software; you can redistribute it and/or modify it under
-; the terms of the GNU General Public License as published by the Free
-; Software Foundation; either version 3, or (at your option) any later
-; version.
-;
-; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-; WARRANTY; without even the implied warranty of MERCHANTABILITY or
-; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-; for more details.
-;
-; You should have received a copy of the GNU General Public License
-; along with GCC; see the file COPYING3. If not see
-; <http://www.gnu.org/licenses/>.
-
-mandroid
-Target Report Mask(ANDROID)
-Generate code for the Android operating system.
diff --git a/gcc-4.2.1/gcc/config/arm/ecos-elf.h b/gcc-4.2.1/gcc/config/arm/ecos-elf.h
deleted file mode 100644
index 22eefe497..000000000
--- a/gcc-4.2.1/gcc/config/arm/ecos-elf.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Definitions for ecos based ARM systems using ELF
- Copyright (C) 1998, 2001 Free Software Foundation, Inc.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* Run-time Target Specification. */
-#undef TARGET_VERSION
-#define TARGET_VERSION fputs (" (ARM/ELF Ecos)", stderr);
-
-#define HAS_INIT_SECTION
-
-#undef INVOKE_main
-
diff --git a/gcc-4.2.1/gcc/config/arm/elf.h b/gcc-4.2.1/gcc/config/arm/elf.h
deleted file mode 100644
index 91ee119ad..000000000
--- a/gcc-4.2.1/gcc/config/arm/elf.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/* Definitions of target machine for GNU compiler.
- For ARM with ELF obj format.
- Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2004, 2005
- Free Software Foundation, Inc.
- Contributed by Philip Blundell <philb@gnu.org> and
- Catherine Moore <clm@cygnus.com>
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-#ifndef OBJECT_FORMAT_ELF
- #error elf.h included before elfos.h
-#endif
-
-#ifndef LOCAL_LABEL_PREFIX
-#define LOCAL_LABEL_PREFIX "."
-#endif
-
-#ifndef SUBTARGET_CPP_SPEC
-#define SUBTARGET_CPP_SPEC "-D__ELF__"
-#endif
-
-#ifndef SUBTARGET_EXTRA_SPECS
-#define SUBTARGET_EXTRA_SPECS \
- { "subtarget_extra_asm_spec", SUBTARGET_EXTRA_ASM_SPEC }, \
- { "subtarget_asm_float_spec", SUBTARGET_ASM_FLOAT_SPEC }, \
- SUBSUBTARGET_EXTRA_SPECS
-#endif
-
-#ifndef SUBTARGET_EXTRA_ASM_SPEC
-#define SUBTARGET_EXTRA_ASM_SPEC ""
-#endif
-
-#ifndef SUBTARGET_ASM_FLOAT_SPEC
-#define SUBTARGET_ASM_FLOAT_SPEC "\
-%{mapcs-float:-mfloat}"
-#endif
-
-#undef SUBSUBTARGET_EXTRA_SPECS
-#define SUBSUBTARGET_EXTRA_SPECS
-
-#ifndef ASM_SPEC
-#define ASM_SPEC "\
-%{mbig-endian:-EB} \
-%{mlittle-endian:-EL} \
-%{mcpu=*:-mcpu=%*} \
-%{march=*:-march=%*} \
-%{mapcs-*:-mapcs-%*} \
-%(subtarget_asm_float_spec) \
-%{mthumb-interwork:-mthumb-interwork} \
-%{msoft-float:-mfloat-abi=soft} %{mhard-float:-mfloat-abi=hard} \
-%{mfloat-abi=*} %{mfpu=*} \
-%(subtarget_extra_asm_spec)"
-#endif
-
-/* The ARM uses @ are a comment character so we need to redefine
- TYPE_OPERAND_FMT. */
-#undef TYPE_OPERAND_FMT
-#define TYPE_OPERAND_FMT "%%%s"
-
-/* We might need a ARM specific header to function declarations. */
-#undef ASM_DECLARE_FUNCTION_NAME
-#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
- do \
- { \
- ARM_DECLARE_FUNCTION_NAME (FILE, NAME, DECL); \
- ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "function"); \
- ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
- ASM_OUTPUT_LABEL(FILE, NAME); \
- ARM_OUTPUT_FN_UNWIND (FILE, TRUE); \
- } \
- while (0)
-
-/* We might need an ARM specific trailer for function declarations. */
-#undef ASM_DECLARE_FUNCTION_SIZE
-#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
- do \
- { \
- ARM_OUTPUT_FN_UNWIND (FILE, FALSE); \
- ARM_DECLARE_FUNCTION_SIZE (FILE, FNAME, DECL); \
- if (!flag_inhibit_size_directive) \
- ASM_OUTPUT_MEASURED_SIZE (FILE, FNAME); \
- } \
- while (0)
-
-/* 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. */
-/* We put ARM jump tables in the text section, because it makes the code
- more efficient, but for Thumb it's better to put them out of band. */
-#define JUMP_TABLES_IN_TEXT_SECTION (TARGET_ARM)
-
-#ifndef LINK_SPEC
-#define LINK_SPEC "%{mbig-endian:-EB} %{mlittle-endian:-EL} -X"
-#endif
-
-/* Run-time Target Specification. */
-#ifndef TARGET_VERSION
-#define TARGET_VERSION fputs (" (ARM/elf)", stderr)
-#endif
-
-#ifndef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_APCS_FRAME)
-#endif
-
-#ifndef MULTILIB_DEFAULTS
-#define MULTILIB_DEFAULTS \
- { "marm", "mlittle-endian", "msoft-float", "mno-thumb-interwork", "fno-leading-underscore" }
-#endif
-
-#define TARGET_ASM_FILE_START_APP_OFF true
-#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
-
-
-/* Output an element in the static constructor array. */
-#undef TARGET_ASM_CONSTRUCTOR
-#define TARGET_ASM_CONSTRUCTOR arm_elf_asm_constructor
-
-/* For PIC code we need to explicitly specify (PLT) and (GOT) relocs. */
-#define NEED_PLT_RELOC flag_pic
-#define NEED_GOT_RELOC flag_pic
-
-/* The ELF assembler handles GOT addressing differently to NetBSD. */
-#define GOT_PCREL 0
-
-/* Biggest alignment supported by the object file format of this
- machine. Use this macro to limit the alignment which can be
- specified using the `__attribute__ ((aligned (N)))' construct. If
- not defined, the default value is `BIGGEST_ALIGNMENT'. */
-#define MAX_OFILE_ALIGNMENT (32768 * 8)
-
-/* Align output to a power of two. Note ".align 0" is redundant,
- and also GAS will treat it as ".align 2" which we do not want. */
-#define ASM_OUTPUT_ALIGN(STREAM, POWER) \
- do \
- { \
- if ((POWER) > 0) \
- fprintf (STREAM, "\t.align\t%d\n", POWER); \
- } \
- while (0)
-
-/* The EABI doesn't provide a way of implementing init_priority. */
-#define SUPPORTS_INIT_PRIORITY (!TARGET_AAPCS_BASED)
diff --git a/gcc-4.2.1/gcc/config/arm/fpa.md b/gcc-4.2.1/gcc/config/arm/fpa.md
deleted file mode 100644
index b801f5a53..000000000
--- a/gcc-4.2.1/gcc/config/arm/fpa.md
+++ /dev/null
@@ -1,750 +0,0 @@
-;;- Machine description for FPA co-processor for ARM cpus.
-;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
-;; 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
-;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
-;; and Martin Simmons (@harleqn.co.uk).
-;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
-
-;; This file is part of GCC.
-
-;; GCC is free software; you can redistribute it and/or modify it
-;; under the terms of the GNU General Public License as published
-;; by the Free Software Foundation; either version 2, or (at your
-;; option) any later version.
-
-;; GCC is distributed in the hope that it will be useful, but WITHOUT
-;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
-;; License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
-
-;; FPA automaton.
-(define_automaton "armfp")
-
-;; Floating point unit (FPA)
-(define_cpu_unit "fpa" "armfp")
-
-; The fpa10 doesn't really have a memory read unit, but it can start
-; to speculatively execute the instruction in the pipeline, provided
-; the data is already loaded, so pretend reads have a delay of 2 (and
-; that the pipeline is infinite).
-(define_cpu_unit "fpa_mem" "arm")
-
-(define_insn_reservation "fdivx" 71
- (and (eq_attr "fpu" "fpa")
- (eq_attr "type" "fdivx"))
- "core+fpa*69")
-
-(define_insn_reservation "fdivd" 59
- (and (eq_attr "fpu" "fpa")
- (eq_attr "type" "fdivd"))
- "core+fpa*57")
-
-(define_insn_reservation "fdivs" 31
- (and (eq_attr "fpu" "fpa")
- (eq_attr "type" "fdivs"))
- "core+fpa*29")
-
-(define_insn_reservation "fmul" 9
- (and (eq_attr "fpu" "fpa")
- (eq_attr "type" "fmul"))
- "core+fpa*7")
-
-(define_insn_reservation "ffmul" 6
- (and (eq_attr "fpu" "fpa")
- (eq_attr "type" "ffmul"))
- "core+fpa*4")
-
-(define_insn_reservation "farith" 4
- (and (eq_attr "fpu" "fpa")
- (eq_attr "type" "farith"))
- "core+fpa*2")
-
-(define_insn_reservation "ffarith" 2
- (and (eq_attr "fpu" "fpa")
- (eq_attr "type" "ffarith"))
- "core+fpa*2")
-
-(define_insn_reservation "r_2_f" 5
- (and (eq_attr "fpu" "fpa")
- (eq_attr "type" "r_2_f"))
- "core+fpa*3")
-
-(define_insn_reservation "f_2_r" 1
- (and (eq_attr "fpu" "fpa")
- (eq_attr "type" "f_2_r"))
- "core+fpa*2")
-
-(define_insn_reservation "f_load" 3
- (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load"))
- "fpa_mem+core*3")
-
-(define_insn_reservation "f_store" 4
- (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store"))
- "core*4")
-
-(define_insn_reservation "r_mem_f" 6
- (and (eq_attr "model_wbuf" "no")
- (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")))
- "core*6")
-
-(define_insn_reservation "f_mem_r" 7
- (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r"))
- "core*7")
-
-
-(define_insn "*addsf3_fpa"
- [(set (match_operand:SF 0 "s_register_operand" "=f,f")
- (plus:SF (match_operand:SF 1 "s_register_operand" "%f,f")
- (match_operand:SF 2 "arm_float_add_operand" "fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "@
- adf%?s\\t%0, %1, %2
- suf%?s\\t%0, %1, #%N2"
- [(set_attr "type" "farith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*adddf3_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f,f")
- (plus:DF (match_operand:DF 1 "s_register_operand" "%f,f")
- (match_operand:DF 2 "arm_float_add_operand" "fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "@
- adf%?d\\t%0, %1, %2
- suf%?d\\t%0, %1, #%N2"
- [(set_attr "type" "farith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*adddf_esfdf_df_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f,f")
- (plus:DF (float_extend:DF
- (match_operand:SF 1 "s_register_operand" "f,f"))
- (match_operand:DF 2 "arm_float_add_operand" "fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "@
- adf%?d\\t%0, %1, %2
- suf%?d\\t%0, %1, #%N2"
- [(set_attr "type" "farith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*adddf_df_esfdf_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (plus:DF (match_operand:DF 1 "s_register_operand" "f")
- (float_extend:DF
- (match_operand:SF 2 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "adf%?d\\t%0, %1, %2"
- [(set_attr "type" "farith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*adddf_esfdf_esfdf_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (plus:DF (float_extend:DF
- (match_operand:SF 1 "s_register_operand" "f"))
- (float_extend:DF
- (match_operand:SF 2 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "adf%?d\\t%0, %1, %2"
- [(set_attr "type" "farith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*subsf3_fpa"
- [(set (match_operand:SF 0 "s_register_operand" "=f,f")
- (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "f,G")
- (match_operand:SF 2 "arm_float_rhs_operand" "fG,f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "@
- suf%?s\\t%0, %1, %2
- rsf%?s\\t%0, %2, %1"
- [(set_attr "type" "farith")]
-)
-
-(define_insn "*subdf3_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f,f")
- (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "f,G")
- (match_operand:DF 2 "arm_float_rhs_operand" "fG,f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "@
- suf%?d\\t%0, %1, %2
- rsf%?d\\t%0, %2, %1"
- [(set_attr "type" "farith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*subdf_esfdf_df_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (minus:DF (float_extend:DF
- (match_operand:SF 1 "s_register_operand" "f"))
- (match_operand:DF 2 "arm_float_rhs_operand" "fG")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "suf%?d\\t%0, %1, %2"
- [(set_attr "type" "farith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*subdf_df_esfdf_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f,f")
- (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "f,G")
- (float_extend:DF
- (match_operand:SF 2 "s_register_operand" "f,f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "@
- suf%?d\\t%0, %1, %2
- rsf%?d\\t%0, %2, %1"
- [(set_attr "type" "farith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*subdf_esfdf_esfdf_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (minus:DF (float_extend:DF
- (match_operand:SF 1 "s_register_operand" "f"))
- (float_extend:DF
- (match_operand:SF 2 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "suf%?d\\t%0, %1, %2"
- [(set_attr "type" "farith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*mulsf3_fpa"
- [(set (match_operand:SF 0 "s_register_operand" "=f")
- (mult:SF (match_operand:SF 1 "s_register_operand" "f")
- (match_operand:SF 2 "arm_float_rhs_operand" "fG")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "fml%?s\\t%0, %1, %2"
- [(set_attr "type" "ffmul")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*muldf3_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (mult:DF (match_operand:DF 1 "s_register_operand" "f")
- (match_operand:DF 2 "arm_float_rhs_operand" "fG")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "muf%?d\\t%0, %1, %2"
- [(set_attr "type" "fmul")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*muldf_esfdf_df_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (mult:DF (float_extend:DF
- (match_operand:SF 1 "s_register_operand" "f"))
- (match_operand:DF 2 "arm_float_rhs_operand" "fG")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "muf%?d\\t%0, %1, %2"
- [(set_attr "type" "fmul")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*muldf_df_esfdf_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (mult:DF (match_operand:DF 1 "s_register_operand" "f")
- (float_extend:DF
- (match_operand:SF 2 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "muf%?d\\t%0, %1, %2"
- [(set_attr "type" "fmul")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*muldf_esfdf_esfdf_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (mult:DF
- (float_extend:DF (match_operand:SF 1 "s_register_operand" "f"))
- (float_extend:DF (match_operand:SF 2 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "muf%?d\\t%0, %1, %2"
- [(set_attr "type" "fmul")
- (set_attr "predicable" "yes")]
-)
-
-;; Division insns
-
-(define_insn "*divsf3_fpa"
- [(set (match_operand:SF 0 "s_register_operand" "=f,f")
- (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "f,G")
- (match_operand:SF 2 "arm_float_rhs_operand" "fG,f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "@
- fdv%?s\\t%0, %1, %2
- frd%?s\\t%0, %2, %1"
- [(set_attr "type" "fdivs")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*divdf3_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f,f")
- (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "f,G")
- (match_operand:DF 2 "arm_float_rhs_operand" "fG,f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "@
- dvf%?d\\t%0, %1, %2
- rdf%?d\\t%0, %2, %1"
- [(set_attr "type" "fdivd")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*divdf_esfdf_df_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (div:DF (float_extend:DF
- (match_operand:SF 1 "s_register_operand" "f"))
- (match_operand:DF 2 "arm_float_rhs_operand" "fG")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "dvf%?d\\t%0, %1, %2"
- [(set_attr "type" "fdivd")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*divdf_df_esfdf_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "fG")
- (float_extend:DF
- (match_operand:SF 2 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "rdf%?d\\t%0, %2, %1"
- [(set_attr "type" "fdivd")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*divdf_esfdf_esfdf_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (div:DF (float_extend:DF
- (match_operand:SF 1 "s_register_operand" "f"))
- (float_extend:DF
- (match_operand:SF 2 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "dvf%?d\\t%0, %1, %2"
- [(set_attr "type" "fdivd")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*modsf3_fpa"
- [(set (match_operand:SF 0 "s_register_operand" "=f")
- (mod:SF (match_operand:SF 1 "s_register_operand" "f")
- (match_operand:SF 2 "arm_float_rhs_operand" "fG")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "rmf%?s\\t%0, %1, %2"
- [(set_attr "type" "fdivs")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*moddf3_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (mod:DF (match_operand:DF 1 "s_register_operand" "f")
- (match_operand:DF 2 "arm_float_rhs_operand" "fG")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "rmf%?d\\t%0, %1, %2"
- [(set_attr "type" "fdivd")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*moddf_esfdf_df_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (mod:DF (float_extend:DF
- (match_operand:SF 1 "s_register_operand" "f"))
- (match_operand:DF 2 "arm_float_rhs_operand" "fG")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "rmf%?d\\t%0, %1, %2"
- [(set_attr "type" "fdivd")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*moddf_df_esfdf_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (mod:DF (match_operand:DF 1 "s_register_operand" "f")
- (float_extend:DF
- (match_operand:SF 2 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "rmf%?d\\t%0, %1, %2"
- [(set_attr "type" "fdivd")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*moddf_esfdf_esfdf_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (mod:DF (float_extend:DF
- (match_operand:SF 1 "s_register_operand" "f"))
- (float_extend:DF
- (match_operand:SF 2 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "rmf%?d\\t%0, %1, %2"
- [(set_attr "type" "fdivd")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*negsf2_fpa"
- [(set (match_operand:SF 0 "s_register_operand" "=f")
- (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "mnf%?s\\t%0, %1"
- [(set_attr "type" "ffarith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*negdf2_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "mnf%?d\\t%0, %1"
- [(set_attr "type" "ffarith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*negdf_esfdf_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (neg:DF (float_extend:DF
- (match_operand:SF 1 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "mnf%?d\\t%0, %1"
- [(set_attr "type" "ffarith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*abssf2_fpa"
- [(set (match_operand:SF 0 "s_register_operand" "=f")
- (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "abs%?s\\t%0, %1"
- [(set_attr "type" "ffarith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*absdf2_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "abs%?d\\t%0, %1"
- [(set_attr "type" "ffarith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*absdf_esfdf_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (abs:DF (float_extend:DF
- (match_operand:SF 1 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "abs%?d\\t%0, %1"
- [(set_attr "type" "ffarith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*sqrtsf2_fpa"
- [(set (match_operand:SF 0 "s_register_operand" "=f")
- (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "sqt%?s\\t%0, %1"
- [(set_attr "type" "float_em")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*sqrtdf2_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "sqt%?d\\t%0, %1"
- [(set_attr "type" "float_em")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*sqrtdf_esfdf_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (sqrt:DF (float_extend:DF
- (match_operand:SF 1 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "sqt%?d\\t%0, %1"
- [(set_attr "type" "float_em")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*floatsisf2_fpa"
- [(set (match_operand:SF 0 "s_register_operand" "=f")
- (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "flt%?s\\t%0, %1"
- [(set_attr "type" "r_2_f")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*floatsidf2_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "flt%?d\\t%0, %1"
- [(set_attr "type" "r_2_f")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*fix_truncsfsi2_fpa"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "fix%?z\\t%0, %1"
- [(set_attr "type" "f_2_r")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*fix_truncdfsi2_fpa"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "fix%?z\\t%0, %1"
- [(set_attr "type" "f_2_r")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*truncdfsf2_fpa"
- [(set (match_operand:SF 0 "s_register_operand" "=f")
- (float_truncate:SF
- (match_operand:DF 1 "s_register_operand" "f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "mvf%?s\\t%0, %1"
- [(set_attr "type" "ffarith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*extendsfdf2_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "mvf%?d\\t%0, %1"
- [(set_attr "type" "ffarith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*movsf_fpa"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m")
- (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
- "TARGET_ARM
- && TARGET_HARD_FLOAT && TARGET_FPA
- && (GET_CODE (operands[0]) != MEM
- || register_operand (operands[1], SFmode))"
- "@
- mvf%?s\\t%0, %1
- mnf%?s\\t%0, #%N1
- ldf%?s\\t%0, %1
- stf%?s\\t%1, %0
- str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
- stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
- mov%?\\t%0, %1
- ldr%?\\t%0, %1\\t%@ float
- str%?\\t%1, %0\\t%@ float"
- [(set_attr "length" "4,4,4,4,8,8,4,4,4")
- (set_attr "predicable" "yes")
- (set_attr "type"
- "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load1,store1")
- (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
- (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
-)
-
-(define_insn "*movdf_fpa"
- [(set (match_operand:DF 0 "nonimmediate_operand"
- "=r,Q,r,m,r, f, f,f, m,!f,!r")
- (match_operand:DF 1 "general_operand"
- "Q, r,r,r,mF,fG,H,mF,f,r, f"))]
- "TARGET_ARM
- && TARGET_HARD_FLOAT && TARGET_FPA
- && (GET_CODE (operands[0]) != MEM
- || register_operand (operands[1], DFmode))"
- "*
- {
- switch (which_alternative)
- {
- default:
- case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
- case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
- case 2: return \"#\";
- case 3: case 4: return output_move_double (operands);
- case 5: return \"mvf%?d\\t%0, %1\";
- case 6: return \"mnf%?d\\t%0, #%N1\";
- case 7: return \"ldf%?d\\t%0, %1\";
- case 8: return \"stf%?d\\t%1, %0\";
- case 9: return output_mov_double_fpa_from_arm (operands);
- case 10: return output_mov_double_arm_from_fpa (operands);
- }
- }
- "
- [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
- (set_attr "predicable" "yes")
- (set_attr "type"
- "load1,store2,*,store2,load1,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
- (set_attr "pool_range" "*,*,*,*,1020,*,*,1024,*,*,*")
- (set_attr "neg_pool_range" "*,*,*,*,1008,*,*,1008,*,*,*")]
-)
-
-;; We treat XFmode as meaning 'internal format'. It's the right size and we
-;; don't use it for anything else. We only support moving between FPA
-;; registers and moving an FPA register to/from memory.
-(define_insn "*movxf_fpa"
- [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,m")
- (match_operand:XF 1 "general_operand" "f,m,f"))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA
- && (register_operand (operands[0], XFmode)
- || register_operand (operands[1], XFmode))"
- "*
- switch (which_alternative)
- {
- default:
- case 0: return \"mvf%?e\\t%0, %1\";
- case 1: if (arm_fpu_arch == FPUTYPE_FPA_EMU2)
- return \"ldf%?e\\t%0, %1\";
- return \"lfm%?\\t%0, 1, %1\";
- case 2: if (arm_fpu_arch == FPUTYPE_FPA_EMU2)
- return \"stf%?e\\t%1, %0\";
- return \"sfm%?\\t%1, 1, %0\";
- }
- "
- [(set_attr "length" "4,4,4")
- (set_attr "predicable" "yes")
- (set_attr "type" "ffarith,f_load,f_store")]
-)
-
-(define_insn "*cmpsf_fpa"
- [(set (reg:CCFP CC_REGNUM)
- (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
- (match_operand:SF 1 "arm_float_add_operand" "fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "@
- cmf%?\\t%0, %1
- cnf%?\\t%0, #%N1"
- [(set_attr "conds" "set")
- (set_attr "type" "f_2_r")]
-)
-
-(define_insn "*cmpdf_fpa"
- [(set (reg:CCFP CC_REGNUM)
- (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
- (match_operand:DF 1 "arm_float_add_operand" "fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "@
- cmf%?\\t%0, %1
- cnf%?\\t%0, #%N1"
- [(set_attr "conds" "set")
- (set_attr "type" "f_2_r")]
-)
-
-(define_insn "*cmpesfdf_df_fpa"
- [(set (reg:CCFP CC_REGNUM)
- (compare:CCFP (float_extend:DF
- (match_operand:SF 0 "s_register_operand" "f,f"))
- (match_operand:DF 1 "arm_float_add_operand" "fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "@
- cmf%?\\t%0, %1
- cnf%?\\t%0, #%N1"
- [(set_attr "conds" "set")
- (set_attr "type" "f_2_r")]
-)
-
-(define_insn "*cmpdf_esfdf_fpa"
- [(set (reg:CCFP CC_REGNUM)
- (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
- (float_extend:DF
- (match_operand:SF 1 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "cmf%?\\t%0, %1"
- [(set_attr "conds" "set")
- (set_attr "type" "f_2_r")]
-)
-
-(define_insn "*cmpsf_trap_fpa"
- [(set (reg:CCFPE CC_REGNUM)
- (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
- (match_operand:SF 1 "arm_float_add_operand" "fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "@
- cmf%?e\\t%0, %1
- cnf%?e\\t%0, #%N1"
- [(set_attr "conds" "set")
- (set_attr "type" "f_2_r")]
-)
-
-(define_insn "*cmpdf_trap_fpa"
- [(set (reg:CCFPE CC_REGNUM)
- (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
- (match_operand:DF 1 "arm_float_add_operand" "fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "@
- cmf%?e\\t%0, %1
- cnf%?e\\t%0, #%N1"
- [(set_attr "conds" "set")
- (set_attr "type" "f_2_r")]
-)
-
-(define_insn "*cmp_esfdf_df_trap_fpa"
- [(set (reg:CCFPE CC_REGNUM)
- (compare:CCFPE (float_extend:DF
- (match_operand:SF 0 "s_register_operand" "f,f"))
- (match_operand:DF 1 "arm_float_add_operand" "fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "@
- cmf%?e\\t%0, %1
- cnf%?e\\t%0, #%N1"
- [(set_attr "conds" "set")
- (set_attr "type" "f_2_r")]
-)
-
-(define_insn "*cmp_df_esfdf_trap_fpa"
- [(set (reg:CCFPE CC_REGNUM)
- (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
- (float_extend:DF
- (match_operand:SF 1 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "cmf%?e\\t%0, %1"
- [(set_attr "conds" "set")
- (set_attr "type" "f_2_r")]
-)
-
-(define_insn "*movsfcc_fpa"
- [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
- (if_then_else:SF
- (match_operator 3 "arm_comparison_operator"
- [(match_operand 4 "cc_register" "") (const_int 0)])
- (match_operand:SF 1 "arm_float_add_operand" "0,0,fG,H,fG,fG,H,H")
- (match_operand:SF 2 "arm_float_add_operand" "fG,H,0,0,fG,H,fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "@
- mvf%D3s\\t%0, %2
- mnf%D3s\\t%0, #%N2
- mvf%d3s\\t%0, %1
- mnf%d3s\\t%0, #%N1
- mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
- mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
- mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
- mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
- [(set_attr "length" "4,4,4,4,8,8,8,8")
- (set_attr "type" "ffarith")
- (set_attr "conds" "use")]
-)
-
-(define_insn "*movdfcc_fpa"
- [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
- (if_then_else:DF
- (match_operator 3 "arm_comparison_operator"
- [(match_operand 4 "cc_register" "") (const_int 0)])
- (match_operand:DF 1 "arm_float_add_operand" "0,0,fG,H,fG,fG,H,H")
- (match_operand:DF 2 "arm_float_add_operand" "fG,H,0,0,fG,H,fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
- "@
- mvf%D3d\\t%0, %2
- mnf%D3d\\t%0, #%N2
- mvf%d3d\\t%0, %1
- mnf%d3d\\t%0, #%N1
- mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
- mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
- mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
- mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
- [(set_attr "length" "4,4,4,4,8,8,8,8")
- (set_attr "type" "ffarith")
- (set_attr "conds" "use")]
-)
diff --git a/gcc-4.2.1/gcc/config/arm/freebsd.h b/gcc-4.2.1/gcc/config/arm/freebsd.h
deleted file mode 100644
index 6bae83def..000000000
--- a/gcc-4.2.1/gcc/config/arm/freebsd.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* Definitions for StrongARM running FreeBSD using the ELF format
- Copyright (C) 2001, 2004 Free Software Foundation, Inc.
- Contributed by David E. O'Brien <obrien@FreeBSD.org> and BSDi.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-
-#undef SUBTARGET_EXTRA_SPECS
-#define SUBTARGET_EXTRA_SPECS \
- { "fbsd_dynamic_linker", FBSD_DYNAMIC_LINKER }
-
-#undef SUBTARGET_CPP_SPEC
-#define SUBTARGET_CPP_SPEC FBSD_CPP_SPEC
-
-#undef LINK_SPEC
-#define LINK_SPEC " \
- %{p:%nconsider using `-pg' instead of `-p' with gprof(1) } \
- %{v:-V} \
- %{assert*} %{R*} %{rpath*} %{defsym*} \
- %{shared:-Bshareable %{h*} %{soname*}} \
- %{!shared: \
- %{!static: \
- %{rdynamic:-export-dynamic} \
- %{!dynamic-linker:-dynamic-linker %(fbsd_dynamic_linker) }} \
- %{static:-Bstatic}} \
- %{symbolic:-Bsymbolic}"
-
-
-/************************[ Target stuff ]***********************************/
-
-/* Define the actual types of some ANSI-mandated types.
- Needs to agree with <machine/ansi.h>. GCC defaults come from c-decl.c,
- c-common.c, and config/<arch>/<arch>.h. */
-
-/* arm.h gets this wrong for FreeBSD. We use the GCC defaults instead. */
-
-#undef SIZE_TYPE
-#define SIZE_TYPE "unsigned int"
-
-#undef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "int"
-
-/* We use the GCC defaults here. */
-#undef WCHAR_TYPE
-
-#undef WCHAR_TYPE_SIZE
-#define WCHAR_TYPE_SIZE 32
-
-#undef SUBTARGET_CPU_DEFAULT
-#define SUBTARGET_CPU_DEFAULT TARGET_CPU_strongarm
-
-#undef TARGET_VERSION
-#define TARGET_VERSION fprintf (stderr, " (FreeBSD/StrongARM ELF)");
diff --git a/gcc-4.2.1/gcc/config/arm/gentune.sh b/gcc-4.2.1/gcc/config/arm/gentune.sh
deleted file mode 100755
index 40c054110..000000000
--- a/gcc-4.2.1/gcc/config/arm/gentune.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/sh
-# Generate arm-tune.md, a file containing the tune attribute from the list of
-# CPUs in arm-cores.def
-
-echo ";; -*- buffer-read-only: t -*-"
-echo ";; Generated automatically by gentune.sh from arm-cores.def"
-
-allcores=`awk -F'[(, ]+' '/^ARM_CORE/ { cores = cores$3"," } END { print cores } ' $1`
-
-echo "(define_attr \"tune\""
-echo " \"$allcores\"" | sed -e 's/,"$/"/'
-echo " (const (symbol_ref \"arm_tune\")))"
diff --git a/gcc-4.2.1/gcc/config/arm/ieee754-df.S b/gcc-4.2.1/gcc/config/arm/ieee754-df.S
deleted file mode 100644
index 74d9f0d9c..000000000
--- a/gcc-4.2.1/gcc/config/arm/ieee754-df.S
+++ /dev/null
@@ -1,1335 +0,0 @@
-/* ieee754-df.S double-precision floating point support for ARM
-
- Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
- Contributed by Nicolas Pitre (nico@cam.org)
-
- 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 into combinations with other programs,
- and to distribute those combinations 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 a combine
- executable.)
-
- 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, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/*
- * Notes:
- *
- * The goal of this code is to be as fast as possible. This is
- * not meant to be easy to understand for the casual reader.
- * For slightly simpler code please see the single precision version
- * of this file.
- *
- * Only the default rounding mode is intended for best performances.
- * Exceptions aren't supported yet, but that can be added quite easily
- * if necessary without impacting performances.
- */
-
-
-@ For FPA, float words are always big-endian.
-@ For VFP, floats words follow the memory system mode.
-#if defined(__VFP_FP__) && !defined(__ARMEB__)
-#define xl r0
-#define xh r1
-#define yl r2
-#define yh r3
-#else
-#define xh r0
-#define xl r1
-#define yh r2
-#define yl r3
-#endif
-
-
-#ifdef L_negdf2
-
-ARM_FUNC_START negdf2
-ARM_FUNC_ALIAS aeabi_dneg negdf2
-
- @ flip sign bit
- eor xh, xh, #0x80000000
- RET
-
- FUNC_END aeabi_dneg
- FUNC_END negdf2
-
-#endif
-
-#ifdef L_addsubdf3
-
-ARM_FUNC_START aeabi_drsub
-
- eor xh, xh, #0x80000000 @ flip sign bit of first arg
- b 1f
-
-ARM_FUNC_START subdf3
-ARM_FUNC_ALIAS aeabi_dsub subdf3
-
- eor yh, yh, #0x80000000 @ flip sign bit of second arg
-#if defined(__INTERWORKING_STUBS__)
- b 1f @ Skip Thumb-code prologue
-#endif
-
-ARM_FUNC_START adddf3
-ARM_FUNC_ALIAS aeabi_dadd adddf3
-
-1: stmfd sp!, {r4, r5, lr}
-
- @ Look for zeroes, equal values, INF, or NAN.
- mov r4, xh, lsl #1
- mov r5, yh, lsl #1
- teq r4, r5
- teqeq xl, yl
- orrnes ip, r4, xl
- orrnes ip, r5, yl
- mvnnes ip, r4, asr #21
- mvnnes ip, r5, asr #21
- beq LSYM(Lad_s)
-
- @ Compute exponent difference. Make largest exponent in r4,
- @ corresponding arg in xh-xl, and positive exponent difference in r5.
- mov r4, r4, lsr #21
- rsbs r5, r4, r5, lsr #21
- rsblt r5, r5, #0
- ble 1f
- add r4, r4, r5
- eor yl, xl, yl
- eor yh, xh, yh
- eor xl, yl, xl
- eor xh, yh, xh
- eor yl, xl, yl
- eor yh, xh, yh
-1:
- @ If exponent difference is too large, return largest argument
- @ already in xh-xl. We need up to 54 bit to handle proper rounding
- @ of 0x1p54 - 1.1.
- cmp r5, #54
- RETLDM "r4, r5" hi
-
- @ Convert mantissa to signed integer.
- tst xh, #0x80000000
- mov xh, xh, lsl #12
- mov ip, #0x00100000
- orr xh, ip, xh, lsr #12
- beq 1f
- rsbs xl, xl, #0
- rsc xh, xh, #0
-1:
- tst yh, #0x80000000
- mov yh, yh, lsl #12
- orr yh, ip, yh, lsr #12
- beq 1f
- rsbs yl, yl, #0
- rsc yh, yh, #0
-1:
- @ If exponent == difference, one or both args were denormalized.
- @ Since this is not common case, rescale them off line.
- teq r4, r5
- beq LSYM(Lad_d)
-LSYM(Lad_x):
-
- @ Compensate for the exponent overlapping the mantissa MSB added later
- sub r4, r4, #1
-
- @ Shift yh-yl right per r5, add to xh-xl, keep leftover bits into ip.
- rsbs lr, r5, #32
- blt 1f
- mov ip, yl, lsl lr
- adds xl, xl, yl, lsr r5
- adc xh, xh, #0
- adds xl, xl, yh, lsl lr
- adcs xh, xh, yh, asr r5
- b 2f
-1: sub r5, r5, #32
- add lr, lr, #32
- cmp yl, #1
- mov ip, yh, lsl lr
- orrcs ip, ip, #2 @ 2 not 1, to allow lsr #1 later
- adds xl, xl, yh, asr r5
- adcs xh, xh, yh, asr #31
-2:
- @ We now have a result in xh-xl-ip.
- @ Keep absolute value in xh-xl-ip, sign in r5 (the n bit was set above)
- and r5, xh, #0x80000000
- bpl LSYM(Lad_p)
- rsbs ip, ip, #0
- rscs xl, xl, #0
- rsc xh, xh, #0
-
- @ Determine how to normalize the result.
-LSYM(Lad_p):
- cmp xh, #0x00100000
- bcc LSYM(Lad_a)
- cmp xh, #0x00200000
- bcc LSYM(Lad_e)
-
- @ Result needs to be shifted right.
- movs xh, xh, lsr #1
- movs xl, xl, rrx
- mov ip, ip, rrx
- add r4, r4, #1
-
- @ Make sure we did not bust our exponent.
- mov r2, r4, lsl #21
- cmn r2, #(2 << 21)
- bcs LSYM(Lad_o)
-
- @ Our result is now properly aligned into xh-xl, remaining bits in ip.
- @ Round with MSB of ip. If halfway between two numbers, round towards
- @ LSB of xl = 0.
- @ Pack final result together.
-LSYM(Lad_e):
- cmp ip, #0x80000000
- moveqs ip, xl, lsr #1
- adcs xl, xl, #0
- adc xh, xh, r4, lsl #20
- orr xh, xh, r5
- RETLDM "r4, r5"
-
- @ Result must be shifted left and exponent adjusted.
-LSYM(Lad_a):
- movs ip, ip, lsl #1
- adcs xl, xl, xl
- adc xh, xh, xh
- tst xh, #0x00100000
- sub r4, r4, #1
- bne LSYM(Lad_e)
-
- @ No rounding necessary since ip will always be 0 at this point.
-LSYM(Lad_l):
-
-#if __ARM_ARCH__ < 5
-
- teq xh, #0
- movne r3, #20
- moveq r3, #52
- moveq xh, xl
- moveq xl, #0
- mov r2, xh
- cmp r2, #(1 << 16)
- movhs r2, r2, lsr #16
- subhs r3, r3, #16
- cmp r2, #(1 << 8)
- movhs r2, r2, lsr #8
- subhs r3, r3, #8
- cmp r2, #(1 << 4)
- movhs r2, r2, lsr #4
- subhs r3, r3, #4
- cmp r2, #(1 << 2)
- subhs r3, r3, #2
- sublo r3, r3, r2, lsr #1
- sub r3, r3, r2, lsr #3
-
-#else
-
- teq xh, #0
- moveq xh, xl
- moveq xl, #0
- clz r3, xh
- addeq r3, r3, #32
- sub r3, r3, #11
-
-#endif
-
- @ determine how to shift the value.
- subs r2, r3, #32
- bge 2f
- adds r2, r2, #12
- ble 1f
-
- @ shift value left 21 to 31 bits, or actually right 11 to 1 bits
- @ since a register switch happened above.
- add ip, r2, #20
- rsb r2, r2, #12
- mov xl, xh, lsl ip
- mov xh, xh, lsr r2
- b 3f
-
- @ actually shift value left 1 to 20 bits, which might also represent
- @ 32 to 52 bits if counting the register switch that happened earlier.
-1: add r2, r2, #20
-2: rsble ip, r2, #32
- mov xh, xh, lsl r2
- orrle xh, xh, xl, lsr ip
- movle xl, xl, lsl r2
-
- @ adjust exponent accordingly.
-3: subs r4, r4, r3
- addge xh, xh, r4, lsl #20
- orrge xh, xh, r5
- RETLDM "r4, r5" ge
-
- @ Exponent too small, denormalize result.
- @ Find out proper shift value.
- mvn r4, r4
- subs r4, r4, #31
- bge 2f
- adds r4, r4, #12
- bgt 1f
-
- @ shift result right of 1 to 20 bits, sign is in r5.
- add r4, r4, #20
- rsb r2, r4, #32
- mov xl, xl, lsr r4
- orr xl, xl, xh, lsl r2
- orr xh, r5, xh, lsr r4
- RETLDM "r4, r5"
-
- @ shift result right of 21 to 31 bits, or left 11 to 1 bits after
- @ a register switch from xh to xl.
-1: rsb r4, r4, #12
- rsb r2, r4, #32
- mov xl, xl, lsr r2
- orr xl, xl, xh, lsl r4
- mov xh, r5
- RETLDM "r4, r5"
-
- @ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch
- @ from xh to xl.
-2: mov xl, xh, lsr r4
- mov xh, r5
- RETLDM "r4, r5"
-
- @ Adjust exponents for denormalized arguments.
- @ Note that r4 must not remain equal to 0.
-LSYM(Lad_d):
- teq r4, #0
- eor yh, yh, #0x00100000
- eoreq xh, xh, #0x00100000
- addeq r4, r4, #1
- subne r5, r5, #1
- b LSYM(Lad_x)
-
-
-LSYM(Lad_s):
- mvns ip, r4, asr #21
- mvnnes ip, r5, asr #21
- beq LSYM(Lad_i)
-
- teq r4, r5
- teqeq xl, yl
- beq 1f
-
- @ Result is x + 0.0 = x or 0.0 + y = y.
- orrs ip, r4, xl
- moveq xh, yh
- moveq xl, yl
- RETLDM "r4, r5"
-
-1: teq xh, yh
-
- @ Result is x - x = 0.
- movne xh, #0
- movne xl, #0
- RETLDM "r4, r5" ne
-
- @ Result is x + x = 2x.
- movs ip, r4, lsr #21
- bne 2f
- movs xl, xl, lsl #1
- adcs xh, xh, xh
- orrcs xh, xh, #0x80000000
- RETLDM "r4, r5"
-2: adds r4, r4, #(2 << 21)
- addcc xh, xh, #(1 << 20)
- RETLDM "r4, r5" cc
- and r5, xh, #0x80000000
-
- @ Overflow: return INF.
-LSYM(Lad_o):
- orr xh, r5, #0x7f000000
- orr xh, xh, #0x00f00000
- mov xl, #0
- RETLDM "r4, r5"
-
- @ At least one of x or y is INF/NAN.
- @ if xh-xl != INF/NAN: return yh-yl (which is INF/NAN)
- @ if yh-yl != INF/NAN: return xh-xl (which is INF/NAN)
- @ if either is NAN: return NAN
- @ if opposite sign: return NAN
- @ otherwise return xh-xl (which is INF or -INF)
-LSYM(Lad_i):
- mvns ip, r4, asr #21
- movne xh, yh
- movne xl, yl
- mvneqs ip, r5, asr #21
- movne yh, xh
- movne yl, xl
- orrs r4, xl, xh, lsl #12
- orreqs r5, yl, yh, lsl #12
- teqeq xh, yh
- orrne xh, xh, #0x00080000 @ quiet NAN
- RETLDM "r4, r5"
-
- FUNC_END aeabi_dsub
- FUNC_END subdf3
- FUNC_END aeabi_dadd
- FUNC_END adddf3
-
-ARM_FUNC_START floatunsidf
-ARM_FUNC_ALIAS aeabi_ui2d floatunsidf
-
- teq r0, #0
- moveq r1, #0
- RETc(eq)
- stmfd sp!, {r4, r5, lr}
- mov r4, #0x400 @ initial exponent
- add r4, r4, #(52-1 - 1)
- mov r5, #0 @ sign bit is 0
- .ifnc xl, r0
- mov xl, r0
- .endif
- mov xh, #0
- b LSYM(Lad_l)
-
- FUNC_END aeabi_ui2d
- FUNC_END floatunsidf
-
-ARM_FUNC_START floatsidf
-ARM_FUNC_ALIAS aeabi_i2d floatsidf
-
- teq r0, #0
- moveq r1, #0
- RETc(eq)
- stmfd sp!, {r4, r5, lr}
- mov r4, #0x400 @ initial exponent
- add r4, r4, #(52-1 - 1)
- ands r5, r0, #0x80000000 @ sign bit in r5
- rsbmi r0, r0, #0 @ absolute value
- .ifnc xl, r0
- mov xl, r0
- .endif
- mov xh, #0
- b LSYM(Lad_l)
-
- FUNC_END aeabi_i2d
- FUNC_END floatsidf
-
-ARM_FUNC_START extendsfdf2
-ARM_FUNC_ALIAS aeabi_f2d extendsfdf2
-
- movs r2, r0, lsl #1 @ toss sign bit
- mov xh, r2, asr #3 @ stretch exponent
- mov xh, xh, rrx @ retrieve sign bit
- mov xl, r2, lsl #28 @ retrieve remaining bits
- andnes r3, r2, #0xff000000 @ isolate exponent
- teqne r3, #0xff000000 @ if not 0, check if INF or NAN
- eorne xh, xh, #0x38000000 @ fixup exponent otherwise.
- RETc(ne) @ and return it.
-
- teq r2, #0 @ if actually 0
- teqne r3, #0xff000000 @ or INF or NAN
- RETc(eq) @ we are done already.
-
- @ value was denormalized. We can normalize it now.
- stmfd sp!, {r4, r5, lr}
- mov r4, #0x380 @ setup corresponding exponent
- and r5, xh, #0x80000000 @ move sign bit in r5
- bic xh, xh, #0x80000000
- b LSYM(Lad_l)
-
- FUNC_END aeabi_f2d
- FUNC_END extendsfdf2
-
-ARM_FUNC_START floatundidf
-ARM_FUNC_ALIAS aeabi_ul2d floatundidf
-
- orrs r2, r0, r1
-#if !defined (__VFP_FP__) && !defined(__SOFTFP__)
- mvfeqd f0, #0.0
-#endif
- RETc(eq)
-
-#if !defined (__VFP_FP__) && !defined(__SOFTFP__)
- @ For hard FPA code we want to return via the tail below so that
- @ we can return the result in f0 as well as in r0/r1 for backwards
- @ compatibility.
- adr ip, LSYM(f0_ret)
- stmfd sp!, {r4, r5, ip, lr}
-#else
- stmfd sp!, {r4, r5, lr}
-#endif
-
- mov r5, #0
- b 2f
-
-ARM_FUNC_START floatdidf
-ARM_FUNC_ALIAS aeabi_l2d floatdidf
-
- orrs r2, r0, r1
-#if !defined (__VFP_FP__) && !defined(__SOFTFP__)
- mvfeqd f0, #0.0
-#endif
- RETc(eq)
-
-#if !defined (__VFP_FP__) && !defined(__SOFTFP__)
- @ For hard FPA code we want to return via the tail below so that
- @ we can return the result in f0 as well as in r0/r1 for backwards
- @ compatibility.
- adr ip, LSYM(f0_ret)
- stmfd sp!, {r4, r5, ip, lr}
-#else
- stmfd sp!, {r4, r5, lr}
-#endif
-
- ands r5, ah, #0x80000000 @ sign bit in r5
- bpl 2f
- rsbs al, al, #0
- rsc ah, ah, #0
-2:
- mov r4, #0x400 @ initial exponent
- add r4, r4, #(52-1 - 1)
-
- @ FPA little-endian: must swap the word order.
- .ifnc xh, ah
- mov ip, al
- mov xh, ah
- mov xl, ip
- .endif
-
- movs ip, xh, lsr #22
- beq LSYM(Lad_p)
-
- @ The value is too big. Scale it down a bit...
- mov r2, #3
- movs ip, ip, lsr #3
- addne r2, r2, #3
- movs ip, ip, lsr #3
- addne r2, r2, #3
- add r2, r2, ip, lsr #3
-
- rsb r3, r2, #32
- mov ip, xl, lsl r3
- mov xl, xl, lsr r2
- orr xl, xl, xh, lsl r3
- mov xh, xh, lsr r2
- add r4, r4, r2
- b LSYM(Lad_p)
-
-#if !defined (__VFP_FP__) && !defined(__SOFTFP__)
-
- @ Legacy code expects the result to be returned in f0. Copy it
- @ there as well.
-LSYM(f0_ret):
- stmfd sp!, {r0, r1}
- ldfd f0, [sp], #8
- RETLDM
-
-#endif
-
- FUNC_END floatdidf
- FUNC_END aeabi_l2d
- FUNC_END floatundidf
- FUNC_END aeabi_ul2d
-
-#endif /* L_addsubdf3 */
-
-#ifdef L_muldivdf3
-
-ARM_FUNC_START muldf3
-ARM_FUNC_ALIAS aeabi_dmul muldf3
- stmfd sp!, {r4, r5, r6, lr}
-
- @ Mask out exponents, trap any zero/denormal/INF/NAN.
- mov ip, #0xff
- orr ip, ip, #0x700
- ands r4, ip, xh, lsr #20
- andnes r5, ip, yh, lsr #20
- teqne r4, ip
- teqne r5, ip
- bleq LSYM(Lml_s)
-
- @ Add exponents together
- add r4, r4, r5
-
- @ Determine final sign.
- eor r6, xh, yh
-
- @ Convert mantissa to unsigned integer.
- @ If power of two, branch to a separate path.
- bic xh, xh, ip, lsl #21
- bic yh, yh, ip, lsl #21
- orrs r5, xl, xh, lsl #12
- orrnes r5, yl, yh, lsl #12
- orr xh, xh, #0x00100000
- orr yh, yh, #0x00100000
- beq LSYM(Lml_1)
-
-#if __ARM_ARCH__ < 4
-
- @ Put sign bit in r6, which will be restored in yl later.
- and r6, r6, #0x80000000
-
- @ Well, no way to make it shorter without the umull instruction.
- stmfd sp!, {r6, r7, r8, r9, sl, fp}
- mov r7, xl, lsr #16
- mov r8, yl, lsr #16
- mov r9, xh, lsr #16
- mov sl, yh, lsr #16
- bic xl, xl, r7, lsl #16
- bic yl, yl, r8, lsl #16
- bic xh, xh, r9, lsl #16
- bic yh, yh, sl, lsl #16
- mul ip, xl, yl
- mul fp, xl, r8
- mov lr, #0
- adds ip, ip, fp, lsl #16
- adc lr, lr, fp, lsr #16
- mul fp, r7, yl
- adds ip, ip, fp, lsl #16
- adc lr, lr, fp, lsr #16
- mul fp, xl, sl
- mov r5, #0
- adds lr, lr, fp, lsl #16
- adc r5, r5, fp, lsr #16
- mul fp, r7, yh
- adds lr, lr, fp, lsl #16
- adc r5, r5, fp, lsr #16
- mul fp, xh, r8
- adds lr, lr, fp, lsl #16
- adc r5, r5, fp, lsr #16
- mul fp, r9, yl
- adds lr, lr, fp, lsl #16
- adc r5, r5, fp, lsr #16
- mul fp, xh, sl
- mul r6, r9, sl
- adds r5, r5, fp, lsl #16
- adc r6, r6, fp, lsr #16
- mul fp, r9, yh
- adds r5, r5, fp, lsl #16
- adc r6, r6, fp, lsr #16
- mul fp, xl, yh
- adds lr, lr, fp
- mul fp, r7, sl
- adcs r5, r5, fp
- mul fp, xh, yl
- adc r6, r6, #0
- adds lr, lr, fp
- mul fp, r9, r8
- adcs r5, r5, fp
- mul fp, r7, r8
- adc r6, r6, #0
- adds lr, lr, fp
- mul fp, xh, yh
- adcs r5, r5, fp
- adc r6, r6, #0
- ldmfd sp!, {yl, r7, r8, r9, sl, fp}
-
-#else
-
- @ Here is the actual multiplication.
- umull ip, lr, xl, yl
- mov r5, #0
- umlal lr, r5, xh, yl
- and yl, r6, #0x80000000
- umlal lr, r5, xl, yh
- mov r6, #0
- umlal r5, r6, xh, yh
-
-#endif
-
- @ The LSBs in ip are only significant for the final rounding.
- @ Fold them into lr.
- teq ip, #0
- orrne lr, lr, #1
-
- @ Adjust result upon the MSB position.
- sub r4, r4, #0xff
- cmp r6, #(1 << (20-11))
- sbc r4, r4, #0x300
- bcs 1f
- movs lr, lr, lsl #1
- adcs r5, r5, r5
- adc r6, r6, r6
-1:
- @ Shift to final position, add sign to result.
- orr xh, yl, r6, lsl #11
- orr xh, xh, r5, lsr #21
- mov xl, r5, lsl #11
- orr xl, xl, lr, lsr #21
- mov lr, lr, lsl #11
-
- @ Check exponent range for under/overflow.
- subs ip, r4, #(254 - 1)
- cmphi ip, #0x700
- bhi LSYM(Lml_u)
-
- @ Round the result, merge final exponent.
- cmp lr, #0x80000000
- moveqs lr, xl, lsr #1
- adcs xl, xl, #0
- adc xh, xh, r4, lsl #20
- RETLDM "r4, r5, r6"
-
- @ Multiplication by 0x1p*: let''s shortcut a lot of code.
-LSYM(Lml_1):
- and r6, r6, #0x80000000
- orr xh, r6, xh
- orr xl, xl, yl
- eor xh, xh, yh
- subs r4, r4, ip, lsr #1
- rsbgts r5, r4, ip
- orrgt xh, xh, r4, lsl #20
- RETLDM "r4, r5, r6" gt
-
- @ Under/overflow: fix things up for the code below.
- orr xh, xh, #0x00100000
- mov lr, #0
- subs r4, r4, #1
-
-LSYM(Lml_u):
- @ Overflow?
- bgt LSYM(Lml_o)
-
- @ Check if denormalized result is possible, otherwise return signed 0.
- cmn r4, #(53 + 1)
- movle xl, #0
- bicle xh, xh, #0x7fffffff
- RETLDM "r4, r5, r6" le
-
- @ Find out proper shift value.
- rsb r4, r4, #0
- subs r4, r4, #32
- bge 2f
- adds r4, r4, #12
- bgt 1f
-
- @ shift result right of 1 to 20 bits, preserve sign bit, round, etc.
- add r4, r4, #20
- rsb r5, r4, #32
- mov r3, xl, lsl r5
- mov xl, xl, lsr r4
- orr xl, xl, xh, lsl r5
- and r2, xh, #0x80000000
- bic xh, xh, #0x80000000
- adds xl, xl, r3, lsr #31
- adc xh, r2, xh, lsr r4
- orrs lr, lr, r3, lsl #1
- biceq xl, xl, r3, lsr #31
- RETLDM "r4, r5, r6"
-
- @ shift result right of 21 to 31 bits, or left 11 to 1 bits after
- @ a register switch from xh to xl. Then round.
-1: rsb r4, r4, #12
- rsb r5, r4, #32
- mov r3, xl, lsl r4
- mov xl, xl, lsr r5
- orr xl, xl, xh, lsl r4
- bic xh, xh, #0x7fffffff
- adds xl, xl, r3, lsr #31
- adc xh, xh, #0
- orrs lr, lr, r3, lsl #1
- biceq xl, xl, r3, lsr #31
- RETLDM "r4, r5, r6"
-
- @ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch
- @ from xh to xl. Leftover bits are in r3-r6-lr for rounding.
-2: rsb r5, r4, #32
- orr lr, lr, xl, lsl r5
- mov r3, xl, lsr r4
- orr r3, r3, xh, lsl r5
- mov xl, xh, lsr r4
- bic xh, xh, #0x7fffffff
- bic xl, xl, xh, lsr r4
- add xl, xl, r3, lsr #31
- orrs lr, lr, r3, lsl #1
- biceq xl, xl, r3, lsr #31
- RETLDM "r4, r5, r6"
-
- @ One or both arguments are denormalized.
- @ Scale them leftwards and preserve sign bit.
-LSYM(Lml_d):
- teq r4, #0
- bne 2f
- and r6, xh, #0x80000000
-1: movs xl, xl, lsl #1
- adc xh, xh, xh
- tst xh, #0x00100000
- subeq r4, r4, #1
- beq 1b
- orr xh, xh, r6
- teq r5, #0
- movne pc, lr
-2: and r6, yh, #0x80000000
-3: movs yl, yl, lsl #1
- adc yh, yh, yh
- tst yh, #0x00100000
- subeq r5, r5, #1
- beq 3b
- orr yh, yh, r6
- mov pc, lr
-
-LSYM(Lml_s):
- @ Isolate the INF and NAN cases away
- teq r4, ip
- and r5, ip, yh, lsr #20
- teqne r5, ip
- beq 1f
-
- @ Here, one or more arguments are either denormalized or zero.
- orrs r6, xl, xh, lsl #1
- orrnes r6, yl, yh, lsl #1
- bne LSYM(Lml_d)
-
- @ Result is 0, but determine sign anyway.
-LSYM(Lml_z):
- eor xh, xh, yh
- bic xh, xh, #0x7fffffff
- mov xl, #0
- RETLDM "r4, r5, r6"
-
-1: @ One or both args are INF or NAN.
- orrs r6, xl, xh, lsl #1
- moveq xl, yl
- moveq xh, yh
- orrnes r6, yl, yh, lsl #1
- beq LSYM(Lml_n) @ 0 * INF or INF * 0 -> NAN
- teq r4, ip
- bne 1f
- orrs r6, xl, xh, lsl #12
- bne LSYM(Lml_n) @ NAN * <anything> -> NAN
-1: teq r5, ip
- bne LSYM(Lml_i)
- orrs r6, yl, yh, lsl #12
- movne xl, yl
- movne xh, yh
- bne LSYM(Lml_n) @ <anything> * NAN -> NAN
-
- @ Result is INF, but we need to determine its sign.
-LSYM(Lml_i):
- eor xh, xh, yh
-
- @ Overflow: return INF (sign already in xh).
-LSYM(Lml_o):
- and xh, xh, #0x80000000
- orr xh, xh, #0x7f000000
- orr xh, xh, #0x00f00000
- mov xl, #0
- RETLDM "r4, r5, r6"
-
- @ Return a quiet NAN.
-LSYM(Lml_n):
- orr xh, xh, #0x7f000000
- orr xh, xh, #0x00f80000
- RETLDM "r4, r5, r6"
-
- FUNC_END aeabi_dmul
- FUNC_END muldf3
-
-ARM_FUNC_START divdf3
-ARM_FUNC_ALIAS aeabi_ddiv divdf3
-
- stmfd sp!, {r4, r5, r6, lr}
-
- @ Mask out exponents, trap any zero/denormal/INF/NAN.
- mov ip, #0xff
- orr ip, ip, #0x700
- ands r4, ip, xh, lsr #20
- andnes r5, ip, yh, lsr #20
- teqne r4, ip
- teqne r5, ip
- bleq LSYM(Ldv_s)
-
- @ Substract divisor exponent from dividend''s.
- sub r4, r4, r5
-
- @ Preserve final sign into lr.
- eor lr, xh, yh
-
- @ Convert mantissa to unsigned integer.
- @ Dividend -> r5-r6, divisor -> yh-yl.
- orrs r5, yl, yh, lsl #12
- mov xh, xh, lsl #12
- beq LSYM(Ldv_1)
- mov yh, yh, lsl #12
- mov r5, #0x10000000
- orr yh, r5, yh, lsr #4
- orr yh, yh, yl, lsr #24
- mov yl, yl, lsl #8
- orr r5, r5, xh, lsr #4
- orr r5, r5, xl, lsr #24
- mov r6, xl, lsl #8
-
- @ Initialize xh with final sign bit.
- and xh, lr, #0x80000000
-
- @ Ensure result will land to known bit position.
- @ Apply exponent bias accordingly.
- cmp r5, yh
- cmpeq r6, yl
- adc r4, r4, #(255 - 2)
- add r4, r4, #0x300
- bcs 1f
- movs yh, yh, lsr #1
- mov yl, yl, rrx
-1:
- @ Perform first substraction to align result to a nibble.
- subs r6, r6, yl
- sbc r5, r5, yh
- movs yh, yh, lsr #1
- mov yl, yl, rrx
- mov xl, #0x00100000
- mov ip, #0x00080000
-
- @ The actual division loop.
-1: subs lr, r6, yl
- sbcs lr, r5, yh
- subcs r6, r6, yl
- movcs r5, lr
- orrcs xl, xl, ip
- movs yh, yh, lsr #1
- mov yl, yl, rrx
- subs lr, r6, yl
- sbcs lr, r5, yh
- subcs r6, r6, yl
- movcs r5, lr
- orrcs xl, xl, ip, lsr #1
- movs yh, yh, lsr #1
- mov yl, yl, rrx
- subs lr, r6, yl
- sbcs lr, r5, yh
- subcs r6, r6, yl
- movcs r5, lr
- orrcs xl, xl, ip, lsr #2
- movs yh, yh, lsr #1
- mov yl, yl, rrx
- subs lr, r6, yl
- sbcs lr, r5, yh
- subcs r6, r6, yl
- movcs r5, lr
- orrcs xl, xl, ip, lsr #3
-
- orrs lr, r5, r6
- beq 2f
- mov r5, r5, lsl #4
- orr r5, r5, r6, lsr #28
- mov r6, r6, lsl #4
- mov yh, yh, lsl #3
- orr yh, yh, yl, lsr #29
- mov yl, yl, lsl #3
- movs ip, ip, lsr #4
- bne 1b
-
- @ We are done with a word of the result.
- @ Loop again for the low word if this pass was for the high word.
- tst xh, #0x00100000
- bne 3f
- orr xh, xh, xl
- mov xl, #0
- mov ip, #0x80000000
- b 1b
-2:
- @ Be sure result starts in the high word.
- tst xh, #0x00100000
- orreq xh, xh, xl
- moveq xl, #0
-3:
- @ Check exponent range for under/overflow.
- subs ip, r4, #(254 - 1)
- cmphi ip, #0x700
- bhi LSYM(Lml_u)
-
- @ Round the result, merge final exponent.
- subs ip, r5, yh
- subeqs ip, r6, yl
- moveqs ip, xl, lsr #1
- adcs xl, xl, #0
- adc xh, xh, r4, lsl #20
- RETLDM "r4, r5, r6"
-
- @ Division by 0x1p*: shortcut a lot of code.
-LSYM(Ldv_1):
- and lr, lr, #0x80000000
- orr xh, lr, xh, lsr #12
- adds r4, r4, ip, lsr #1
- rsbgts r5, r4, ip
- orrgt xh, xh, r4, lsl #20
- RETLDM "r4, r5, r6" gt
-
- orr xh, xh, #0x00100000
- mov lr, #0
- subs r4, r4, #1
- b LSYM(Lml_u)
-
- @ Result mightt need to be denormalized: put remainder bits
- @ in lr for rounding considerations.
-LSYM(Ldv_u):
- orr lr, r5, r6
- b LSYM(Lml_u)
-
- @ One or both arguments is either INF, NAN or zero.
-LSYM(Ldv_s):
- and r5, ip, yh, lsr #20
- teq r4, ip
- teqeq r5, ip
- beq LSYM(Lml_n) @ INF/NAN / INF/NAN -> NAN
- teq r4, ip
- bne 1f
- orrs r4, xl, xh, lsl #12
- bne LSYM(Lml_n) @ NAN / <anything> -> NAN
- teq r5, ip
- bne LSYM(Lml_i) @ INF / <anything> -> INF
- mov xl, yl
- mov xh, yh
- b LSYM(Lml_n) @ INF / (INF or NAN) -> NAN
-1: teq r5, ip
- bne 2f
- orrs r5, yl, yh, lsl #12
- beq LSYM(Lml_z) @ <anything> / INF -> 0
- mov xl, yl
- mov xh, yh
- b LSYM(Lml_n) @ <anything> / NAN -> NAN
-2: @ If both are nonzero, we need to normalize and resume above.
- orrs r6, xl, xh, lsl #1
- orrnes r6, yl, yh, lsl #1
- bne LSYM(Lml_d)
- @ One or both arguments are 0.
- orrs r4, xl, xh, lsl #1
- bne LSYM(Lml_i) @ <non_zero> / 0 -> INF
- orrs r5, yl, yh, lsl #1
- bne LSYM(Lml_z) @ 0 / <non_zero> -> 0
- b LSYM(Lml_n) @ 0 / 0 -> NAN
-
- FUNC_END aeabi_ddiv
- FUNC_END divdf3
-
-#endif /* L_muldivdf3 */
-
-#ifdef L_cmpdf2
-
-@ Note: only r0 (return value) and ip are clobbered here.
-
-ARM_FUNC_START gtdf2
-ARM_FUNC_ALIAS gedf2 gtdf2
- mov ip, #-1
- b 1f
-
-ARM_FUNC_START ltdf2
-ARM_FUNC_ALIAS ledf2 ltdf2
- mov ip, #1
- b 1f
-
-ARM_FUNC_START cmpdf2
-ARM_FUNC_ALIAS nedf2 cmpdf2
-ARM_FUNC_ALIAS eqdf2 cmpdf2
- mov ip, #1 @ how should we specify unordered here?
-
-1: str ip, [sp, #-4]
-
- @ Trap any INF/NAN first.
- mov ip, xh, lsl #1
- mvns ip, ip, asr #21
- mov ip, yh, lsl #1
- mvnnes ip, ip, asr #21
- beq 3f
-
- @ Test for equality.
- @ Note that 0.0 is equal to -0.0.
-2: orrs ip, xl, xh, lsl #1 @ if x == 0.0 or -0.0
- orreqs ip, yl, yh, lsl #1 @ and y == 0.0 or -0.0
- teqne xh, yh @ or xh == yh
- teqeq xl, yl @ and xl == yl
- moveq r0, #0 @ then equal.
- RETc(eq)
-
- @ Clear C flag
- cmn r0, #0
-
- @ Compare sign,
- teq xh, yh
-
- @ Compare values if same sign
- cmppl xh, yh
- cmpeq xl, yl
-
- @ Result:
- movcs r0, yh, asr #31
- mvncc r0, yh, asr #31
- orr r0, r0, #1
- RET
-
- @ Look for a NAN.
-3: mov ip, xh, lsl #1
- mvns ip, ip, asr #21
- bne 4f
- orrs ip, xl, xh, lsl #12
- bne 5f @ x is NAN
-4: mov ip, yh, lsl #1
- mvns ip, ip, asr #21
- bne 2b
- orrs ip, yl, yh, lsl #12
- beq 2b @ y is not NAN
-5: ldr r0, [sp, #-4] @ unordered return code
- RET
-
- FUNC_END gedf2
- FUNC_END gtdf2
- FUNC_END ledf2
- FUNC_END ltdf2
- FUNC_END nedf2
- FUNC_END eqdf2
- FUNC_END cmpdf2
-
-ARM_FUNC_START aeabi_cdrcmple
-
- mov ip, r0
- mov r0, r2
- mov r2, ip
- mov ip, r1
- mov r1, r3
- mov r3, ip
- b 6f
-
-ARM_FUNC_START aeabi_cdcmpeq
-ARM_FUNC_ALIAS aeabi_cdcmple aeabi_cdcmpeq
-
- @ The status-returning routines are required to preserve all
- @ registers except ip, lr, and cpsr.
-6: stmfd sp!, {r0, lr}
- ARM_CALL cmpdf2
- @ Set the Z flag correctly, and the C flag unconditionally.
- cmp r0, #0
- @ Clear the C flag if the return value was -1, indicating
- @ that the first operand was smaller than the second.
- cmnmi r0, #0
- RETLDM "r0"
-
- FUNC_END aeabi_cdcmple
- FUNC_END aeabi_cdcmpeq
- FUNC_END aeabi_cdrcmple
-
-ARM_FUNC_START aeabi_dcmpeq
-
- str lr, [sp, #-8]!
- ARM_CALL aeabi_cdcmple
- moveq r0, #1 @ Equal to.
- movne r0, #0 @ Less than, greater than, or unordered.
- RETLDM
-
- FUNC_END aeabi_dcmpeq
-
-ARM_FUNC_START aeabi_dcmplt
-
- str lr, [sp, #-8]!
- ARM_CALL aeabi_cdcmple
- movcc r0, #1 @ Less than.
- movcs r0, #0 @ Equal to, greater than, or unordered.
- RETLDM
-
- FUNC_END aeabi_dcmplt
-
-ARM_FUNC_START aeabi_dcmple
-
- str lr, [sp, #-8]!
- ARM_CALL aeabi_cdcmple
- movls r0, #1 @ Less than or equal to.
- movhi r0, #0 @ Greater than or unordered.
- RETLDM
-
- FUNC_END aeabi_dcmple
-
-ARM_FUNC_START aeabi_dcmpge
-
- str lr, [sp, #-8]!
- ARM_CALL aeabi_cdrcmple
- movls r0, #1 @ Operand 2 is less than or equal to operand 1.
- movhi r0, #0 @ Operand 2 greater than operand 1, or unordered.
- RETLDM
-
- FUNC_END aeabi_dcmpge
-
-ARM_FUNC_START aeabi_dcmpgt
-
- str lr, [sp, #-8]!
- ARM_CALL aeabi_cdrcmple
- movcc r0, #1 @ Operand 2 is less than operand 1.
- movcs r0, #0 @ Operand 2 is greater than or equal to operand 1,
- @ or they are unordered.
- RETLDM
-
- FUNC_END aeabi_dcmpgt
-
-#endif /* L_cmpdf2 */
-
-#ifdef L_unorddf2
-
-ARM_FUNC_START unorddf2
-ARM_FUNC_ALIAS aeabi_dcmpun unorddf2
-
- mov ip, xh, lsl #1
- mvns ip, ip, asr #21
- bne 1f
- orrs ip, xl, xh, lsl #12
- bne 3f @ x is NAN
-1: mov ip, yh, lsl #1
- mvns ip, ip, asr #21
- bne 2f
- orrs ip, yl, yh, lsl #12
- bne 3f @ y is NAN
-2: mov r0, #0 @ arguments are ordered.
- RET
-
-3: mov r0, #1 @ arguments are unordered.
- RET
-
- FUNC_END aeabi_dcmpun
- FUNC_END unorddf2
-
-#endif /* L_unorddf2 */
-
-#ifdef L_fixdfsi
-
-ARM_FUNC_START fixdfsi
-ARM_FUNC_ALIAS aeabi_d2iz fixdfsi
-
- @ check exponent range.
- mov r2, xh, lsl #1
- adds r2, r2, #(1 << 21)
- bcs 2f @ value is INF or NAN
- bpl 1f @ value is too small
- mov r3, #(0xfffffc00 + 31)
- subs r2, r3, r2, asr #21
- bls 3f @ value is too large
-
- @ scale value
- mov r3, xh, lsl #11
- orr r3, r3, #0x80000000
- orr r3, r3, xl, lsr #21
- tst xh, #0x80000000 @ the sign bit
- mov r0, r3, lsr r2
- rsbne r0, r0, #0
- RET
-
-1: mov r0, #0
- RET
-
-2: orrs xl, xl, xh, lsl #12
- bne 4f @ x is NAN.
-3: ands r0, xh, #0x80000000 @ the sign bit
- moveq r0, #0x7fffffff @ maximum signed positive si
- RET
-
-4: mov r0, #0 @ How should we convert NAN?
- RET
-
- FUNC_END aeabi_d2iz
- FUNC_END fixdfsi
-
-#endif /* L_fixdfsi */
-
-#ifdef L_fixunsdfsi
-
-ARM_FUNC_START fixunsdfsi
-ARM_FUNC_ALIAS aeabi_d2uiz fixunsdfsi
-
- @ check exponent range.
- movs r2, xh, lsl #1
- bcs 1f @ value is negative
- adds r2, r2, #(1 << 21)
- bcs 2f @ value is INF or NAN
- bpl 1f @ value is too small
- mov r3, #(0xfffffc00 + 31)
- subs r2, r3, r2, asr #21
- bmi 3f @ value is too large
-
- @ scale value
- mov r3, xh, lsl #11
- orr r3, r3, #0x80000000
- orr r3, r3, xl, lsr #21
- mov r0, r3, lsr r2
- RET
-
-1: mov r0, #0
- RET
-
-2: orrs xl, xl, xh, lsl #12
- bne 4f @ value is NAN.
-3: mov r0, #0xffffffff @ maximum unsigned si
- RET
-
-4: mov r0, #0 @ How should we convert NAN?
- RET
-
- FUNC_END aeabi_d2uiz
- FUNC_END fixunsdfsi
-
-#endif /* L_fixunsdfsi */
-
-#ifdef L_truncdfsf2
-
-ARM_FUNC_START truncdfsf2
-ARM_FUNC_ALIAS aeabi_d2f truncdfsf2
-
- @ check exponent range.
- mov r2, xh, lsl #1
- subs r3, r2, #((1023 - 127) << 21)
- subcss ip, r3, #(1 << 21)
- rsbcss ip, ip, #(254 << 21)
- bls 2f @ value is out of range
-
-1: @ shift and round mantissa
- and ip, xh, #0x80000000
- mov r2, xl, lsl #3
- orr xl, ip, xl, lsr #29
- cmp r2, #0x80000000
- adc r0, xl, r3, lsl #2
- biceq r0, r0, #1
- RET
-
-2: @ either overflow or underflow
- tst xh, #0x40000000
- bne 3f @ overflow
-
- @ check if denormalized value is possible
- adds r2, r3, #(23 << 21)
- andlt r0, xh, #0x80000000 @ too small, return signed 0.
- RETc(lt)
-
- @ denormalize value so we can resume with the code above afterwards.
- orr xh, xh, #0x00100000
- mov r2, r2, lsr #21
- rsb r2, r2, #24
- rsb ip, r2, #32
- movs r3, xl, lsl ip
- mov xl, xl, lsr r2
- orrne xl, xl, #1 @ fold r3 for rounding considerations.
- mov r3, xh, lsl #11
- mov r3, r3, lsr #11
- orr xl, xl, r3, lsl ip
- mov r3, r3, lsr r2
- mov r3, r3, lsl #1
- b 1b
-
-3: @ chech for NAN
- mvns r3, r2, asr #21
- bne 5f @ simple overflow
- orrs r3, xl, xh, lsl #12
- movne r0, #0x7f000000
- orrne r0, r0, #0x00c00000
- RETc(ne) @ return NAN
-
-5: @ return INF with sign
- and r0, xh, #0x80000000
- orr r0, r0, #0x7f000000
- orr r0, r0, #0x00800000
- RET
-
- FUNC_END aeabi_d2f
- FUNC_END truncdfsf2
-
-#endif /* L_truncdfsf2 */
diff --git a/gcc-4.2.1/gcc/config/arm/ieee754-sf.S b/gcc-4.2.1/gcc/config/arm/ieee754-sf.S
deleted file mode 100644
index f74f458dd..000000000
--- a/gcc-4.2.1/gcc/config/arm/ieee754-sf.S
+++ /dev/null
@@ -1,976 +0,0 @@
-/* ieee754-sf.S single-precision floating point support for ARM
-
- Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
- Contributed by Nicolas Pitre (nico@cam.org)
-
- 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 into combinations with other programs,
- and to distribute those combinations 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 a combine
- executable.)
-
- 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, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/*
- * Notes:
- *
- * The goal of this code is to be as fast as possible. This is
- * not meant to be easy to understand for the casual reader.
- *
- * Only the default rounding mode is intended for best performances.
- * Exceptions aren't supported yet, but that can be added quite easily
- * if necessary without impacting performances.
- */
-
-#ifdef L_negsf2
-
-ARM_FUNC_START negsf2
-ARM_FUNC_ALIAS aeabi_fneg negsf2
-
- eor r0, r0, #0x80000000 @ flip sign bit
- RET
-
- FUNC_END aeabi_fneg
- FUNC_END negsf2
-
-#endif
-
-#ifdef L_addsubsf3
-
-ARM_FUNC_START aeabi_frsub
-
- eor r0, r0, #0x80000000 @ flip sign bit of first arg
- b 1f
-
-ARM_FUNC_START subsf3
-ARM_FUNC_ALIAS aeabi_fsub subsf3
-
- eor r1, r1, #0x80000000 @ flip sign bit of second arg
-#if defined(__INTERWORKING_STUBS__)
- b 1f @ Skip Thumb-code prologue
-#endif
-
-ARM_FUNC_START addsf3
-ARM_FUNC_ALIAS aeabi_fadd addsf3
-
-1: @ Look for zeroes, equal values, INF, or NAN.
- movs r2, r0, lsl #1
- movnes r3, r1, lsl #1
- teqne r2, r3
- mvnnes ip, r2, asr #24
- mvnnes ip, r3, asr #24
- beq LSYM(Lad_s)
-
- @ Compute exponent difference. Make largest exponent in r2,
- @ corresponding arg in r0, and positive exponent difference in r3.
- mov r2, r2, lsr #24
- rsbs r3, r2, r3, lsr #24
- addgt r2, r2, r3
- eorgt r1, r0, r1
- eorgt r0, r1, r0
- eorgt r1, r0, r1
- rsblt r3, r3, #0
-
- @ If exponent difference is too large, return largest argument
- @ already in r0. We need up to 25 bit to handle proper rounding
- @ of 0x1p25 - 1.1.
- cmp r3, #25
- RETc(hi)
-
- @ Convert mantissa to signed integer.
- tst r0, #0x80000000
- orr r0, r0, #0x00800000
- bic r0, r0, #0xff000000
- rsbne r0, r0, #0
- tst r1, #0x80000000
- orr r1, r1, #0x00800000
- bic r1, r1, #0xff000000
- rsbne r1, r1, #0
-
- @ If exponent == difference, one or both args were denormalized.
- @ Since this is not common case, rescale them off line.
- teq r2, r3
- beq LSYM(Lad_d)
-LSYM(Lad_x):
-
- @ Compensate for the exponent overlapping the mantissa MSB added later
- sub r2, r2, #1
-
- @ Shift and add second arg to first arg in r0.
- @ Keep leftover bits into r1.
- adds r0, r0, r1, asr r3
- rsb r3, r3, #32
- mov r1, r1, lsl r3
-
- @ Keep absolute value in r0-r1, sign in r3 (the n bit was set above)
- and r3, r0, #0x80000000
- bpl LSYM(Lad_p)
- rsbs r1, r1, #0
- rsc r0, r0, #0
-
- @ Determine how to normalize the result.
-LSYM(Lad_p):
- cmp r0, #0x00800000
- bcc LSYM(Lad_a)
- cmp r0, #0x01000000
- bcc LSYM(Lad_e)
-
- @ Result needs to be shifted right.
- movs r0, r0, lsr #1
- mov r1, r1, rrx
- add r2, r2, #1
-
- @ Make sure we did not bust our exponent.
- cmp r2, #254
- bhs LSYM(Lad_o)
-
- @ Our result is now properly aligned into r0, remaining bits in r1.
- @ Pack final result together.
- @ Round with MSB of r1. If halfway between two numbers, round towards
- @ LSB of r0 = 0.
-LSYM(Lad_e):
- cmp r1, #0x80000000
- adc r0, r0, r2, lsl #23
- biceq r0, r0, #1
- orr r0, r0, r3
- RET
-
- @ Result must be shifted left and exponent adjusted.
-LSYM(Lad_a):
- movs r1, r1, lsl #1
- adc r0, r0, r0
- tst r0, #0x00800000
- sub r2, r2, #1
- bne LSYM(Lad_e)
-
- @ No rounding necessary since r1 will always be 0 at this point.
-LSYM(Lad_l):
-
-#if __ARM_ARCH__ < 5
-
- movs ip, r0, lsr #12
- moveq r0, r0, lsl #12
- subeq r2, r2, #12
- tst r0, #0x00ff0000
- moveq r0, r0, lsl #8
- subeq r2, r2, #8
- tst r0, #0x00f00000
- moveq r0, r0, lsl #4
- subeq r2, r2, #4
- tst r0, #0x00c00000
- moveq r0, r0, lsl #2
- subeq r2, r2, #2
- cmp r0, #0x00800000
- movcc r0, r0, lsl #1
- sbcs r2, r2, #0
-
-#else
-
- clz ip, r0
- sub ip, ip, #8
- subs r2, r2, ip
- mov r0, r0, lsl ip
-
-#endif
-
- @ Final result with sign
- @ If exponent negative, denormalize result.
- addge r0, r0, r2, lsl #23
- rsblt r2, r2, #0
- orrge r0, r0, r3
- orrlt r0, r3, r0, lsr r2
- RET
-
- @ Fixup and adjust bit position for denormalized arguments.
- @ Note that r2 must not remain equal to 0.
-LSYM(Lad_d):
- teq r2, #0
- eor r1, r1, #0x00800000
- eoreq r0, r0, #0x00800000
- addeq r2, r2, #1
- subne r3, r3, #1
- b LSYM(Lad_x)
-
-LSYM(Lad_s):
- mov r3, r1, lsl #1
-
- mvns ip, r2, asr #24
- mvnnes ip, r3, asr #24
- beq LSYM(Lad_i)
-
- teq r2, r3
- beq 1f
-
- @ Result is x + 0.0 = x or 0.0 + y = y.
- teq r2, #0
- moveq r0, r1
- RET
-
-1: teq r0, r1
-
- @ Result is x - x = 0.
- movne r0, #0
- RETc(ne)
-
- @ Result is x + x = 2x.
- tst r2, #0xff000000
- bne 2f
- movs r0, r0, lsl #1
- orrcs r0, r0, #0x80000000
- RET
-2: adds r2, r2, #(2 << 24)
- addcc r0, r0, #(1 << 23)
- RETc(cc)
- and r3, r0, #0x80000000
-
- @ Overflow: return INF.
-LSYM(Lad_o):
- orr r0, r3, #0x7f000000
- orr r0, r0, #0x00800000
- RET
-
- @ At least one of r0/r1 is INF/NAN.
- @ if r0 != INF/NAN: return r1 (which is INF/NAN)
- @ if r1 != INF/NAN: return r0 (which is INF/NAN)
- @ if r0 or r1 is NAN: return NAN
- @ if opposite sign: return NAN
- @ otherwise return r0 (which is INF or -INF)
-LSYM(Lad_i):
- mvns r2, r2, asr #24
- movne r0, r1
- mvneqs r3, r3, asr #24
- movne r1, r0
- movs r2, r0, lsl #9
- moveqs r3, r1, lsl #9
- teqeq r0, r1
- orrne r0, r0, #0x00400000 @ quiet NAN
- RET
-
- FUNC_END aeabi_frsub
- FUNC_END aeabi_fadd
- FUNC_END addsf3
- FUNC_END aeabi_fsub
- FUNC_END subsf3
-
-ARM_FUNC_START floatunsisf
-ARM_FUNC_ALIAS aeabi_ui2f floatunsisf
-
- mov r3, #0
- b 1f
-
-ARM_FUNC_START floatsisf
-ARM_FUNC_ALIAS aeabi_i2f floatsisf
-
- ands r3, r0, #0x80000000
- rsbmi r0, r0, #0
-
-1: movs ip, r0
- RETc(eq)
-
- @ Add initial exponent to sign
- orr r3, r3, #((127 + 23) << 23)
-
- .ifnc ah, r0
- mov ah, r0
- .endif
- mov al, #0
- b 2f
-
- FUNC_END aeabi_i2f
- FUNC_END floatsisf
- FUNC_END aeabi_ui2f
- FUNC_END floatunsisf
-
-ARM_FUNC_START floatundisf
-ARM_FUNC_ALIAS aeabi_ul2f floatundisf
-
- orrs r2, r0, r1
-#if !defined (__VFP_FP__) && !defined(__SOFTFP__)
- mvfeqs f0, #0.0
-#endif
- RETc(eq)
-
- mov r3, #0
- b 1f
-
-ARM_FUNC_START floatdisf
-ARM_FUNC_ALIAS aeabi_l2f floatdisf
-
- orrs r2, r0, r1
-#if !defined (__VFP_FP__) && !defined(__SOFTFP__)
- mvfeqs f0, #0.0
-#endif
- RETc(eq)
-
- ands r3, ah, #0x80000000 @ sign bit in r3
- bpl 1f
- rsbs al, al, #0
- rsc ah, ah, #0
-1:
-#if !defined (__VFP_FP__) && !defined(__SOFTFP__)
- @ For hard FPA code we want to return via the tail below so that
- @ we can return the result in f0 as well as in r0 for backwards
- @ compatibility.
- str lr, [sp, #-8]!
- adr lr, LSYM(f0_ret)
-#endif
-
- movs ip, ah
- moveq ip, al
- moveq ah, al
- moveq al, #0
-
- @ Add initial exponent to sign
- orr r3, r3, #((127 + 23 + 32) << 23)
- subeq r3, r3, #(32 << 23)
-2: sub r3, r3, #(1 << 23)
-
-#if __ARM_ARCH__ < 5
-
- mov r2, #23
- cmp ip, #(1 << 16)
- movhs ip, ip, lsr #16
- subhs r2, r2, #16
- cmp ip, #(1 << 8)
- movhs ip, ip, lsr #8
- subhs r2, r2, #8
- cmp ip, #(1 << 4)
- movhs ip, ip, lsr #4
- subhs r2, r2, #4
- cmp ip, #(1 << 2)
- subhs r2, r2, #2
- sublo r2, r2, ip, lsr #1
- subs r2, r2, ip, lsr #3
-
-#else
-
- clz r2, ip
- subs r2, r2, #8
-
-#endif
-
- sub r3, r3, r2, lsl #23
- blt 3f
-
- add r3, r3, ah, lsl r2
- mov ip, al, lsl r2
- rsb r2, r2, #32
- cmp ip, #0x80000000
- adc r0, r3, al, lsr r2
- biceq r0, r0, #1
- RET
-
-3: add r2, r2, #32
- mov ip, ah, lsl r2
- rsb r2, r2, #32
- orrs al, al, ip, lsl #1
- adc r0, r3, ah, lsr r2
- biceq r0, r0, ip, lsr #31
- RET
-
-#if !defined (__VFP_FP__) && !defined(__SOFTFP__)
-
-LSYM(f0_ret):
- str r0, [sp, #-4]!
- ldfs f0, [sp], #4
- RETLDM
-
-#endif
-
- FUNC_END floatdisf
- FUNC_END aeabi_l2f
- FUNC_END floatundisf
- FUNC_END aeabi_ul2f
-
-#endif /* L_addsubsf3 */
-
-#ifdef L_muldivsf3
-
-ARM_FUNC_START mulsf3
-ARM_FUNC_ALIAS aeabi_fmul mulsf3
-
- @ Mask out exponents, trap any zero/denormal/INF/NAN.
- mov ip, #0xff
- ands r2, ip, r0, lsr #23
- andnes r3, ip, r1, lsr #23
- teqne r2, ip
- teqne r3, ip
- beq LSYM(Lml_s)
-LSYM(Lml_x):
-
- @ Add exponents together
- add r2, r2, r3
-
- @ Determine final sign.
- eor ip, r0, r1
-
- @ Convert mantissa to unsigned integer.
- @ If power of two, branch to a separate path.
- @ Make up for final alignment.
- movs r0, r0, lsl #9
- movnes r1, r1, lsl #9
- beq LSYM(Lml_1)
- mov r3, #0x08000000
- orr r0, r3, r0, lsr #5
- orr r1, r3, r1, lsr #5
-
-#if __ARM_ARCH__ < 4
-
- @ Put sign bit in r3, which will be restored into r0 later.
- and r3, ip, #0x80000000
-
- @ Well, no way to make it shorter without the umull instruction.
- stmfd sp!, {r3, r4, r5}
- mov r4, r0, lsr #16
- mov r5, r1, lsr #16
- bic r0, r0, r4, lsl #16
- bic r1, r1, r5, lsl #16
- mul ip, r4, r5
- mul r3, r0, r1
- mul r0, r5, r0
- mla r0, r4, r1, r0
- adds r3, r3, r0, lsl #16
- adc r1, ip, r0, lsr #16
- ldmfd sp!, {r0, r4, r5}
-
-#else
-
- @ The actual multiplication.
- umull r3, r1, r0, r1
-
- @ Put final sign in r0.
- and r0, ip, #0x80000000
-
-#endif
-
- @ Adjust result upon the MSB position.
- cmp r1, #(1 << 23)
- movcc r1, r1, lsl #1
- orrcc r1, r1, r3, lsr #31
- movcc r3, r3, lsl #1
-
- @ Add sign to result.
- orr r0, r0, r1
-
- @ Apply exponent bias, check for under/overflow.
- sbc r2, r2, #127
- cmp r2, #(254 - 1)
- bhi LSYM(Lml_u)
-
- @ Round the result, merge final exponent.
- cmp r3, #0x80000000
- adc r0, r0, r2, lsl #23
- biceq r0, r0, #1
- RET
-
- @ Multiplication by 0x1p*: let''s shortcut a lot of code.
-LSYM(Lml_1):
- teq r0, #0
- and ip, ip, #0x80000000
- moveq r1, r1, lsl #9
- orr r0, ip, r0, lsr #9
- orr r0, r0, r1, lsr #9
- subs r2, r2, #127
- rsbgts r3, r2, #255
- orrgt r0, r0, r2, lsl #23
- RETc(gt)
-
- @ Under/overflow: fix things up for the code below.
- orr r0, r0, #0x00800000
- mov r3, #0
- subs r2, r2, #1
-
-LSYM(Lml_u):
- @ Overflow?
- bgt LSYM(Lml_o)
-
- @ Check if denormalized result is possible, otherwise return signed 0.
- cmn r2, #(24 + 1)
- bicle r0, r0, #0x7fffffff
- RETc(le)
-
- @ Shift value right, round, etc.
- rsb r2, r2, #0
- movs r1, r0, lsl #1
- mov r1, r1, lsr r2
- rsb r2, r2, #32
- mov ip, r0, lsl r2
- movs r0, r1, rrx
- adc r0, r0, #0
- orrs r3, r3, ip, lsl #1
- biceq r0, r0, ip, lsr #31
- RET
-
- @ One or both arguments are denormalized.
- @ Scale them leftwards and preserve sign bit.
-LSYM(Lml_d):
- teq r2, #0
- and ip, r0, #0x80000000
-1: moveq r0, r0, lsl #1
- tsteq r0, #0x00800000
- subeq r2, r2, #1
- beq 1b
- orr r0, r0, ip
- teq r3, #0
- and ip, r1, #0x80000000
-2: moveq r1, r1, lsl #1
- tsteq r1, #0x00800000
- subeq r3, r3, #1
- beq 2b
- orr r1, r1, ip
- b LSYM(Lml_x)
-
-LSYM(Lml_s):
- @ Isolate the INF and NAN cases away
- and r3, ip, r1, lsr #23
- teq r2, ip
- teqne r3, ip
- beq 1f
-
- @ Here, one or more arguments are either denormalized or zero.
- bics ip, r0, #0x80000000
- bicnes ip, r1, #0x80000000
- bne LSYM(Lml_d)
-
- @ Result is 0, but determine sign anyway.
-LSYM(Lml_z):
- eor r0, r0, r1
- bic r0, r0, #0x7fffffff
- RET
-
-1: @ One or both args are INF or NAN.
- teq r0, #0x0
- teqne r0, #0x80000000
- moveq r0, r1
- teqne r1, #0x0
- teqne r1, #0x80000000
- beq LSYM(Lml_n) @ 0 * INF or INF * 0 -> NAN
- teq r2, ip
- bne 1f
- movs r2, r0, lsl #9
- bne LSYM(Lml_n) @ NAN * <anything> -> NAN
-1: teq r3, ip
- bne LSYM(Lml_i)
- movs r3, r1, lsl #9
- movne r0, r1
- bne LSYM(Lml_n) @ <anything> * NAN -> NAN
-
- @ Result is INF, but we need to determine its sign.
-LSYM(Lml_i):
- eor r0, r0, r1
-
- @ Overflow: return INF (sign already in r0).
-LSYM(Lml_o):
- and r0, r0, #0x80000000
- orr r0, r0, #0x7f000000
- orr r0, r0, #0x00800000
- RET
-
- @ Return a quiet NAN.
-LSYM(Lml_n):
- orr r0, r0, #0x7f000000
- orr r0, r0, #0x00c00000
- RET
-
- FUNC_END aeabi_fmul
- FUNC_END mulsf3
-
-ARM_FUNC_START divsf3
-ARM_FUNC_ALIAS aeabi_fdiv divsf3
-
- @ Mask out exponents, trap any zero/denormal/INF/NAN.
- mov ip, #0xff
- ands r2, ip, r0, lsr #23
- andnes r3, ip, r1, lsr #23
- teqne r2, ip
- teqne r3, ip
- beq LSYM(Ldv_s)
-LSYM(Ldv_x):
-
- @ Substract divisor exponent from dividend''s
- sub r2, r2, r3
-
- @ Preserve final sign into ip.
- eor ip, r0, r1
-
- @ Convert mantissa to unsigned integer.
- @ Dividend -> r3, divisor -> r1.
- movs r1, r1, lsl #9
- mov r0, r0, lsl #9
- beq LSYM(Ldv_1)
- mov r3, #0x10000000
- orr r1, r3, r1, lsr #4
- orr r3, r3, r0, lsr #4
-
- @ Initialize r0 (result) with final sign bit.
- and r0, ip, #0x80000000
-
- @ Ensure result will land to known bit position.
- @ Apply exponent bias accordingly.
- cmp r3, r1
- movcc r3, r3, lsl #1
- adc r2, r2, #(127 - 2)
-
- @ The actual division loop.
- mov ip, #0x00800000
-1: cmp r3, r1
- subcs r3, r3, r1
- orrcs r0, r0, ip
- cmp r3, r1, lsr #1
- subcs r3, r3, r1, lsr #1
- orrcs r0, r0, ip, lsr #1
- cmp r3, r1, lsr #2
- subcs r3, r3, r1, lsr #2
- orrcs r0, r0, ip, lsr #2
- cmp r3, r1, lsr #3
- subcs r3, r3, r1, lsr #3
- orrcs r0, r0, ip, lsr #3
- movs r3, r3, lsl #4
- movnes ip, ip, lsr #4
- bne 1b
-
- @ Check exponent for under/overflow.
- cmp r2, #(254 - 1)
- bhi LSYM(Lml_u)
-
- @ Round the result, merge final exponent.
- cmp r3, r1
- adc r0, r0, r2, lsl #23
- biceq r0, r0, #1
- RET
-
- @ Division by 0x1p*: let''s shortcut a lot of code.
-LSYM(Ldv_1):
- and ip, ip, #0x80000000
- orr r0, ip, r0, lsr #9
- adds r2, r2, #127
- rsbgts r3, r2, #255
- orrgt r0, r0, r2, lsl #23
- RETc(gt)
-
- orr r0, r0, #0x00800000
- mov r3, #0
- subs r2, r2, #1
- b LSYM(Lml_u)
-
- @ One or both arguments are denormalized.
- @ Scale them leftwards and preserve sign bit.
-LSYM(Ldv_d):
- teq r2, #0
- and ip, r0, #0x80000000
-1: moveq r0, r0, lsl #1
- tsteq r0, #0x00800000
- subeq r2, r2, #1
- beq 1b
- orr r0, r0, ip
- teq r3, #0
- and ip, r1, #0x80000000
-2: moveq r1, r1, lsl #1
- tsteq r1, #0x00800000
- subeq r3, r3, #1
- beq 2b
- orr r1, r1, ip
- b LSYM(Ldv_x)
-
- @ One or both arguments are either INF, NAN, zero or denormalized.
-LSYM(Ldv_s):
- and r3, ip, r1, lsr #23
- teq r2, ip
- bne 1f
- movs r2, r0, lsl #9
- bne LSYM(Lml_n) @ NAN / <anything> -> NAN
- teq r3, ip
- bne LSYM(Lml_i) @ INF / <anything> -> INF
- mov r0, r1
- b LSYM(Lml_n) @ INF / (INF or NAN) -> NAN
-1: teq r3, ip
- bne 2f
- movs r3, r1, lsl #9
- beq LSYM(Lml_z) @ <anything> / INF -> 0
- mov r0, r1
- b LSYM(Lml_n) @ <anything> / NAN -> NAN
-2: @ If both are nonzero, we need to normalize and resume above.
- bics ip, r0, #0x80000000
- bicnes ip, r1, #0x80000000
- bne LSYM(Ldv_d)
- @ One or both arguments are zero.
- bics r2, r0, #0x80000000
- bne LSYM(Lml_i) @ <non_zero> / 0 -> INF
- bics r3, r1, #0x80000000
- bne LSYM(Lml_z) @ 0 / <non_zero> -> 0
- b LSYM(Lml_n) @ 0 / 0 -> NAN
-
- FUNC_END aeabi_fdiv
- FUNC_END divsf3
-
-#endif /* L_muldivsf3 */
-
-#ifdef L_cmpsf2
-
- @ The return value in r0 is
- @
- @ 0 if the operands are equal
- @ 1 if the first operand is greater than the second, or
- @ the operands are unordered and the operation is
- @ CMP, LT, LE, NE, or EQ.
- @ -1 if the first operand is less than the second, or
- @ the operands are unordered and the operation is GT
- @ or GE.
- @
- @ The Z flag will be set iff the operands are equal.
- @
- @ The following registers are clobbered by this function:
- @ ip, r0, r1, r2, r3
-
-ARM_FUNC_START gtsf2
-ARM_FUNC_ALIAS gesf2 gtsf2
- mov ip, #-1
- b 1f
-
-ARM_FUNC_START ltsf2
-ARM_FUNC_ALIAS lesf2 ltsf2
- mov ip, #1
- b 1f
-
-ARM_FUNC_START cmpsf2
-ARM_FUNC_ALIAS nesf2 cmpsf2
-ARM_FUNC_ALIAS eqsf2 cmpsf2
- mov ip, #1 @ how should we specify unordered here?
-
-1: str ip, [sp, #-4]
-
- @ Trap any INF/NAN first.
- mov r2, r0, lsl #1
- mov r3, r1, lsl #1
- mvns ip, r2, asr #24
- mvnnes ip, r3, asr #24
- beq 3f
-
- @ Compare values.
- @ Note that 0.0 is equal to -0.0.
-2: orrs ip, r2, r3, lsr #1 @ test if both are 0, clear C flag
- teqne r0, r1 @ if not 0 compare sign
- subpls r0, r2, r3 @ if same sign compare values, set r0
-
- @ Result:
- movhi r0, r1, asr #31
- mvnlo r0, r1, asr #31
- orrne r0, r0, #1
- RET
-
- @ Look for a NAN.
-3: mvns ip, r2, asr #24
- bne 4f
- movs ip, r0, lsl #9
- bne 5f @ r0 is NAN
-4: mvns ip, r3, asr #24
- bne 2b
- movs ip, r1, lsl #9
- beq 2b @ r1 is not NAN
-5: ldr r0, [sp, #-4] @ return unordered code.
- RET
-
- FUNC_END gesf2
- FUNC_END gtsf2
- FUNC_END lesf2
- FUNC_END ltsf2
- FUNC_END nesf2
- FUNC_END eqsf2
- FUNC_END cmpsf2
-
-ARM_FUNC_START aeabi_cfrcmple
-
- mov ip, r0
- mov r0, r1
- mov r1, ip
- b 6f
-
-ARM_FUNC_START aeabi_cfcmpeq
-ARM_FUNC_ALIAS aeabi_cfcmple aeabi_cfcmpeq
-
- @ The status-returning routines are required to preserve all
- @ registers except ip, lr, and cpsr.
-6: stmfd sp!, {r0, r1, r2, r3, lr}
- ARM_CALL cmpsf2
- @ Set the Z flag correctly, and the C flag unconditionally.
- cmp r0, #0
- @ Clear the C flag if the return value was -1, indicating
- @ that the first operand was smaller than the second.
- cmnmi r0, #0
- RETLDM "r0, r1, r2, r3"
-
- FUNC_END aeabi_cfcmple
- FUNC_END aeabi_cfcmpeq
- FUNC_END aeabi_cfrcmple
-
-ARM_FUNC_START aeabi_fcmpeq
-
- str lr, [sp, #-8]!
- ARM_CALL aeabi_cfcmple
- moveq r0, #1 @ Equal to.
- movne r0, #0 @ Less than, greater than, or unordered.
- RETLDM
-
- FUNC_END aeabi_fcmpeq
-
-ARM_FUNC_START aeabi_fcmplt
-
- str lr, [sp, #-8]!
- ARM_CALL aeabi_cfcmple
- movcc r0, #1 @ Less than.
- movcs r0, #0 @ Equal to, greater than, or unordered.
- RETLDM
-
- FUNC_END aeabi_fcmplt
-
-ARM_FUNC_START aeabi_fcmple
-
- str lr, [sp, #-8]!
- ARM_CALL aeabi_cfcmple
- movls r0, #1 @ Less than or equal to.
- movhi r0, #0 @ Greater than or unordered.
- RETLDM
-
- FUNC_END aeabi_fcmple
-
-ARM_FUNC_START aeabi_fcmpge
-
- str lr, [sp, #-8]!
- ARM_CALL aeabi_cfrcmple
- movls r0, #1 @ Operand 2 is less than or equal to operand 1.
- movhi r0, #0 @ Operand 2 greater than operand 1, or unordered.
- RETLDM
-
- FUNC_END aeabi_fcmpge
-
-ARM_FUNC_START aeabi_fcmpgt
-
- str lr, [sp, #-8]!
- ARM_CALL aeabi_cfrcmple
- movcc r0, #1 @ Operand 2 is less than operand 1.
- movcs r0, #0 @ Operand 2 is greater than or equal to operand 1,
- @ or they are unordered.
- RETLDM
-
- FUNC_END aeabi_fcmpgt
-
-#endif /* L_cmpsf2 */
-
-#ifdef L_unordsf2
-
-ARM_FUNC_START unordsf2
-ARM_FUNC_ALIAS aeabi_fcmpun unordsf2
-
- mov r2, r0, lsl #1
- mov r3, r1, lsl #1
- mvns ip, r2, asr #24
- bne 1f
- movs ip, r0, lsl #9
- bne 3f @ r0 is NAN
-1: mvns ip, r3, asr #24
- bne 2f
- movs ip, r1, lsl #9
- bne 3f @ r1 is NAN
-2: mov r0, #0 @ arguments are ordered.
- RET
-3: mov r0, #1 @ arguments are unordered.
- RET
-
- FUNC_END aeabi_fcmpun
- FUNC_END unordsf2
-
-#endif /* L_unordsf2 */
-
-#ifdef L_fixsfsi
-
-ARM_FUNC_START fixsfsi
-ARM_FUNC_ALIAS aeabi_f2iz fixsfsi
-
- @ check exponent range.
- mov r2, r0, lsl #1
- cmp r2, #(127 << 24)
- bcc 1f @ value is too small
- mov r3, #(127 + 31)
- subs r2, r3, r2, lsr #24
- bls 2f @ value is too large
-
- @ scale value
- mov r3, r0, lsl #8
- orr r3, r3, #0x80000000
- tst r0, #0x80000000 @ the sign bit
- mov r0, r3, lsr r2
- rsbne r0, r0, #0
- RET
-
-1: mov r0, #0
- RET
-
-2: cmp r2, #(127 + 31 - 0xff)
- bne 3f
- movs r2, r0, lsl #9
- bne 4f @ r0 is NAN.
-3: ands r0, r0, #0x80000000 @ the sign bit
- moveq r0, #0x7fffffff @ the maximum signed positive si
- RET
-
-4: mov r0, #0 @ What should we convert NAN to?
- RET
-
- FUNC_END aeabi_f2iz
- FUNC_END fixsfsi
-
-#endif /* L_fixsfsi */
-
-#ifdef L_fixunssfsi
-
-ARM_FUNC_START fixunssfsi
-ARM_FUNC_ALIAS aeabi_f2uiz fixunssfsi
-
- @ check exponent range.
- movs r2, r0, lsl #1
- bcs 1f @ value is negative
- cmp r2, #(127 << 24)
- bcc 1f @ value is too small
- mov r3, #(127 + 31)
- subs r2, r3, r2, lsr #24
- bmi 2f @ value is too large
-
- @ scale the value
- mov r3, r0, lsl #8
- orr r3, r3, #0x80000000
- mov r0, r3, lsr r2
- RET
-
-1: mov r0, #0
- RET
-
-2: cmp r2, #(127 + 31 - 0xff)
- bne 3f
- movs r2, r0, lsl #9
- bne 4f @ r0 is NAN.
-3: mov r0, #0xffffffff @ maximum unsigned si
- RET
-
-4: mov r0, #0 @ What should we convert NAN to?
- RET
-
- FUNC_END aeabi_f2uiz
- FUNC_END fixunssfsi
-
-#endif /* L_fixunssfsi */
diff --git a/gcc-4.2.1/gcc/config/arm/iwmmxt.md b/gcc-4.2.1/gcc/config/arm/iwmmxt.md
deleted file mode 100644
index 380d4b954..000000000
--- a/gcc-4.2.1/gcc/config/arm/iwmmxt.md
+++ /dev/null
@@ -1,1528 +0,0 @@
-;; Patterns for the Intel Wireless MMX technology architecture.
-;; Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
-;; Contributed by Red Hat.
-
-;; This file is part of GCC.
-
-;; GCC is free software; you can redistribute it and/or modify it under
-;; the terms of the GNU General Public License as published by the Free
-;; Software Foundation; either version 2, or (at your option) any later
-;; version.
-
-;; GCC is distributed in the hope that it will be useful, but WITHOUT
-;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
-;; License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
-
-(define_insn "iwmmxt_iordi3"
- [(set (match_operand:DI 0 "register_operand" "=y,?&r,?&r")
- (ior:DI (match_operand:DI 1 "register_operand" "%y,0,r")
- (match_operand:DI 2 "register_operand" "y,r,r")))]
- "TARGET_REALLY_IWMMXT"
- "@
- wor%?\\t%0, %1, %2
- #
- #"
- [(set_attr "predicable" "yes")
- (set_attr "length" "4,8,8")])
-
-(define_insn "iwmmxt_xordi3"
- [(set (match_operand:DI 0 "register_operand" "=y,?&r,?&r")
- (xor:DI (match_operand:DI 1 "register_operand" "%y,0,r")
- (match_operand:DI 2 "register_operand" "y,r,r")))]
- "TARGET_REALLY_IWMMXT"
- "@
- wxor%?\\t%0, %1, %2
- #
- #"
- [(set_attr "predicable" "yes")
- (set_attr "length" "4,8,8")])
-
-(define_insn "iwmmxt_anddi3"
- [(set (match_operand:DI 0 "register_operand" "=y,?&r,?&r")
- (and:DI (match_operand:DI 1 "register_operand" "%y,0,r")
- (match_operand:DI 2 "register_operand" "y,r,r")))]
- "TARGET_REALLY_IWMMXT"
- "@
- wand%?\\t%0, %1, %2
- #
- #"
- [(set_attr "predicable" "yes")
- (set_attr "length" "4,8,8")])
-
-(define_insn "iwmmxt_nanddi3"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (and:DI (match_operand:DI 1 "register_operand" "y")
- (not:DI (match_operand:DI 2 "register_operand" "y"))))]
- "TARGET_REALLY_IWMMXT"
- "wandn%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "*iwmmxt_arm_movdi"
- [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, m,y,y,yr,y,yrUy")
- (match_operand:DI 1 "di_operand" "rIK,mi,r,y,yr,y,yrUy,y"))]
- "TARGET_REALLY_IWMMXT
- && ( register_operand (operands[0], DImode)
- || register_operand (operands[1], DImode))"
- "*
-{
- switch (which_alternative)
- {
- default:
- return output_move_double (operands);
- case 0:
- return \"#\";
- case 3:
- return \"wmov%?\\t%0,%1\";
- case 4:
- return \"tmcrr%?\\t%0,%Q1,%R1\";
- case 5:
- return \"tmrrc%?\\t%Q0,%R0,%1\";
- case 6:
- return \"wldrd%?\\t%0,%1\";
- case 7:
- return \"wstrd%?\\t%1,%0\";
- }
-}"
- [(set_attr "length" "8,8,8,4,4,4,4,4")
- (set_attr "type" "*,load1,store2,*,*,*,*,*")
- (set_attr "pool_range" "*,1020,*,*,*,*,*,*")
- (set_attr "neg_pool_range" "*,1012,*,*,*,*,*,*")]
-)
-
-(define_insn "*iwmmxt_movsi_insn"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m,z,r,?z,Uy,z")
- (match_operand:SI 1 "general_operand" "rI,K,mi,r,r,z,Uy,z,z"))]
- "TARGET_REALLY_IWMMXT
- && ( register_operand (operands[0], SImode)
- || register_operand (operands[1], SImode))"
- "*
- switch (which_alternative)
- {
- case 0: return \"mov\\t%0, %1\";
- case 1: return \"mvn\\t%0, #%B1\";
- case 2: return \"ldr\\t%0, %1\";
- case 3: return \"str\\t%1, %0\";
- case 4: return \"tmcr\\t%0, %1\";
- case 5: return \"tmrc\\t%0, %1\";
- case 6: return arm_output_load_gr (operands);
- case 7: return \"wstrw\\t%1, %0\";
- default:return \"wstrw\\t%1, [sp, #-4]!\;wldrw\\t%0, [sp], #4\\t@move CG reg\";
- }"
- [(set_attr "type" "*,*,load1,store1,*,*,load1,store1,*")
- (set_attr "length" "*,*,*, *,*,*, 16, *,8")
- (set_attr "pool_range" "*,*,4096, *,*,*,1024, *,*")
- (set_attr "neg_pool_range" "*,*,4084, *,*,*, *, 1012,*")
- ;; Note - the "predicable" attribute is not allowed to have alternatives.
- ;; Since the wSTRw wCx instruction is not predicable, we cannot support
- ;; predicating any of the alternatives in this template. Instead,
- ;; we do the predication ourselves, in cond_iwmmxt_movsi_insn.
- (set_attr "predicable" "no")
- ;; Also - we have to pretend that these insns clobber the condition code
- ;; bits as otherwise arm_final_prescan_insn() will try to conditionalize
- ;; them.
- (set_attr "conds" "clob")]
-)
-
-;; Because iwmmxt_movsi_insn is not predicable, we provide the
-;; cond_exec version explicitly, with appropriate constraints.
-
-(define_insn "*cond_iwmmxt_movsi_insn"
- [(cond_exec
- (match_operator 2 "arm_comparison_operator"
- [(match_operand 3 "cc_register" "")
- (const_int 0)])
- (set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m,z,r")
- (match_operand:SI 1 "general_operand" "rI,K,mi,r,r,z")))]
- "TARGET_REALLY_IWMMXT
- && ( register_operand (operands[0], SImode)
- || register_operand (operands[1], SImode))"
- "*
- switch (which_alternative)
- {
- case 0: return \"mov%?\\t%0, %1\";
- case 1: return \"mvn%?\\t%0, #%B1\";
- case 2: return \"ldr%?\\t%0, %1\";
- case 3: return \"str%?\\t%1, %0\";
- case 4: return \"tmcr%?\\t%0, %1\";
- default: return \"tmrc%?\\t%0, %1\";
- }"
- [(set_attr "type" "*,*,load1,store1,*,*")
- (set_attr "pool_range" "*,*,4096, *,*,*")
- (set_attr "neg_pool_range" "*,*,4084, *,*,*")]
-)
-
-(define_insn "movv8qi_internal"
- [(set (match_operand:V8QI 0 "nonimmediate_operand" "=y,m,y,?r,?y,?r")
- (match_operand:V8QI 1 "general_operand" "y,y,mi,y,r,mi"))]
- "TARGET_REALLY_IWMMXT"
- "*
- switch (which_alternative)
- {
- case 0: return \"wmov%?\\t%0, %1\";
- case 1: return \"wstrd%?\\t%1, %0\";
- case 2: return \"wldrd%?\\t%0, %1\";
- case 3: return \"tmrrc%?\\t%Q0, %R0, %1\";
- case 4: return \"tmcrr%?\\t%0, %Q1, %R1\";
- default: return output_move_double (operands);
- }"
- [(set_attr "predicable" "yes")
- (set_attr "length" "4, 4, 4,4,4, 8")
- (set_attr "type" "*,store1,load1,*,*,load1")
- (set_attr "pool_range" "*, *, 256,*,*, 256")
- (set_attr "neg_pool_range" "*, *, 244,*,*, 244")])
-
-(define_insn "movv4hi_internal"
- [(set (match_operand:V4HI 0 "nonimmediate_operand" "=y,m,y,?r,?y,?r")
- (match_operand:V4HI 1 "general_operand" "y,y,mi,y,r,mi"))]
- "TARGET_REALLY_IWMMXT"
- "*
- switch (which_alternative)
- {
- case 0: return \"wmov%?\\t%0, %1\";
- case 1: return \"wstrd%?\\t%1, %0\";
- case 2: return \"wldrd%?\\t%0, %1\";
- case 3: return \"tmrrc%?\\t%Q0, %R0, %1\";
- case 4: return \"tmcrr%?\\t%0, %Q1, %R1\";
- default: return output_move_double (operands);
- }"
- [(set_attr "predicable" "yes")
- (set_attr "length" "4, 4, 4,4,4, 8")
- (set_attr "type" "*,store1,load1,*,*,load1")
- (set_attr "pool_range" "*, *, 256,*,*, 256")
- (set_attr "neg_pool_range" "*, *, 244,*,*, 244")])
-
-(define_insn "movv2si_internal"
- [(set (match_operand:V2SI 0 "nonimmediate_operand" "=y,m,y,?r,?y,?r")
- (match_operand:V2SI 1 "general_operand" "y,y,mi,y,r,mi"))]
- "TARGET_REALLY_IWMMXT"
- "*
- switch (which_alternative)
- {
- case 0: return \"wmov%?\\t%0, %1\";
- case 1: return \"wstrd%?\\t%1, %0\";
- case 2: return \"wldrd%?\\t%0, %1\";
- case 3: return \"tmrrc%?\\t%Q0, %R0, %1\";
- case 4: return \"tmcrr%?\\t%0, %Q1, %R1\";
- default: return output_move_double (operands);
- }"
- [(set_attr "predicable" "yes")
- (set_attr "length" "4, 4, 4,4,4, 24")
- (set_attr "type" "*,store1,load1,*,*,load1")
- (set_attr "pool_range" "*, *, 256,*,*, 256")
- (set_attr "neg_pool_range" "*, *, 244,*,*, 244")])
-
-;; This pattern should not be needed. It is to match a
-;; wierd case generated by GCC when no optimizations are
-;; enabled. (Try compiling gcc/testsuite/gcc.c-torture/
-;; compile/simd-5.c at -O0). The mode for operands[1] is
-;; deliberately omitted.
-(define_insn "movv2si_internal_2"
- [(set (match_operand:V2SI 0 "nonimmediate_operand" "=?r")
- (match_operand 1 "immediate_operand" "mi"))]
- "TARGET_REALLY_IWMMXT"
- "* return output_move_double (operands);"
- [(set_attr "predicable" "yes")
- (set_attr "length" "8")
- (set_attr "type" "load1")
- (set_attr "pool_range" "256")
- (set_attr "neg_pool_range" "244")])
-
-;; Vector add/subtract
-
-(define_insn "addv8qi3"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (plus:V8QI (match_operand:V8QI 1 "register_operand" "y")
- (match_operand:V8QI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "waddb%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "addv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (plus:V4HI (match_operand:V4HI 1 "register_operand" "y")
- (match_operand:V4HI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "waddh%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "addv2si3"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (plus:V2SI (match_operand:V2SI 1 "register_operand" "y")
- (match_operand:V2SI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "waddw%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "ssaddv8qi3"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (ss_plus:V8QI (match_operand:V8QI 1 "register_operand" "y")
- (match_operand:V8QI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "waddbss%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "ssaddv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (ss_plus:V4HI (match_operand:V4HI 1 "register_operand" "y")
- (match_operand:V4HI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "waddhss%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "ssaddv2si3"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (ss_plus:V2SI (match_operand:V2SI 1 "register_operand" "y")
- (match_operand:V2SI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "waddwss%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "usaddv8qi3"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (us_plus:V8QI (match_operand:V8QI 1 "register_operand" "y")
- (match_operand:V8QI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "waddbus%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "usaddv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (us_plus:V4HI (match_operand:V4HI 1 "register_operand" "y")
- (match_operand:V4HI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "waddhus%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "usaddv2si3"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (us_plus:V2SI (match_operand:V2SI 1 "register_operand" "y")
- (match_operand:V2SI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "waddwus%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "subv8qi3"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (minus:V8QI (match_operand:V8QI 1 "register_operand" "y")
- (match_operand:V8QI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wsubb%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "subv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (minus:V4HI (match_operand:V4HI 1 "register_operand" "y")
- (match_operand:V4HI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wsubh%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "subv2si3"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (minus:V2SI (match_operand:V2SI 1 "register_operand" "y")
- (match_operand:V2SI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wsubw%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "sssubv8qi3"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (ss_minus:V8QI (match_operand:V8QI 1 "register_operand" "y")
- (match_operand:V8QI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wsubbss%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "sssubv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (ss_minus:V4HI (match_operand:V4HI 1 "register_operand" "y")
- (match_operand:V4HI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wsubhss%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "sssubv2si3"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (ss_minus:V2SI (match_operand:V2SI 1 "register_operand" "y")
- (match_operand:V2SI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wsubwss%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "ussubv8qi3"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (us_minus:V8QI (match_operand:V8QI 1 "register_operand" "y")
- (match_operand:V8QI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wsubbus%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "ussubv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (us_minus:V4HI (match_operand:V4HI 1 "register_operand" "y")
- (match_operand:V4HI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wsubhus%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "ussubv2si3"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (us_minus:V2SI (match_operand:V2SI 1 "register_operand" "y")
- (match_operand:V2SI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wsubwus%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "mulv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (mult:V4HI (match_operand:V4HI 1 "register_operand" "y")
- (match_operand:V4HI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wmulul%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "smulv4hi3_highpart"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (truncate:V4HI
- (lshiftrt:V4SI
- (mult:V4SI (sign_extend:V4SI (match_operand:V4HI 1 "register_operand" "y"))
- (sign_extend:V4SI (match_operand:V4HI 2 "register_operand" "y")))
- (const_int 16))))]
- "TARGET_REALLY_IWMMXT"
- "wmulsm%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "umulv4hi3_highpart"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (truncate:V4HI
- (lshiftrt:V4SI
- (mult:V4SI (zero_extend:V4SI (match_operand:V4HI 1 "register_operand" "y"))
- (zero_extend:V4SI (match_operand:V4HI 2 "register_operand" "y")))
- (const_int 16))))]
- "TARGET_REALLY_IWMMXT"
- "wmulum%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wmacs"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (unspec:DI [(match_operand:DI 1 "register_operand" "0")
- (match_operand:V4HI 2 "register_operand" "y")
- (match_operand:V4HI 3 "register_operand" "y")] UNSPEC_WMACS))]
- "TARGET_REALLY_IWMMXT"
- "wmacs%?\\t%0, %2, %3"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wmacsz"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (unspec:DI [(match_operand:V4HI 1 "register_operand" "y")
- (match_operand:V4HI 2 "register_operand" "y")] UNSPEC_WMACSZ))]
- "TARGET_REALLY_IWMMXT"
- "wmacsz%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wmacu"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (unspec:DI [(match_operand:DI 1 "register_operand" "0")
- (match_operand:V4HI 2 "register_operand" "y")
- (match_operand:V4HI 3 "register_operand" "y")] UNSPEC_WMACU))]
- "TARGET_REALLY_IWMMXT"
- "wmacu%?\\t%0, %2, %3"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wmacuz"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (unspec:DI [(match_operand:V4HI 1 "register_operand" "y")
- (match_operand:V4HI 2 "register_operand" "y")] UNSPEC_WMACUZ))]
- "TARGET_REALLY_IWMMXT"
- "wmacuz%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-;; Same as xordi3, but don't show input operands so that we don't think
-;; they are live.
-(define_insn "iwmmxt_clrdi"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (unspec:DI [(const_int 0)] UNSPEC_CLRDI))]
- "TARGET_REALLY_IWMMXT"
- "wxor%?\\t%0, %0, %0"
- [(set_attr "predicable" "yes")])
-
-;; Seems like cse likes to generate these, so we have to support them.
-
-(define_insn "*iwmmxt_clrv8qi"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (const_vector:V8QI [(const_int 0) (const_int 0)
- (const_int 0) (const_int 0)
- (const_int 0) (const_int 0)
- (const_int 0) (const_int 0)]))]
- "TARGET_REALLY_IWMMXT"
- "wxor%?\\t%0, %0, %0"
- [(set_attr "predicable" "yes")])
-
-(define_insn "*iwmmxt_clrv4hi"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (const_vector:V4HI [(const_int 0) (const_int 0)
- (const_int 0) (const_int 0)]))]
- "TARGET_REALLY_IWMMXT"
- "wxor%?\\t%0, %0, %0"
- [(set_attr "predicable" "yes")])
-
-(define_insn "*iwmmxt_clrv2si"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (const_vector:V2SI [(const_int 0) (const_int 0)]))]
- "TARGET_REALLY_IWMMXT"
- "wxor%?\\t%0, %0, %0"
- [(set_attr "predicable" "yes")])
-
-;; Unsigned averages/sum of absolute differences
-
-(define_insn "iwmmxt_uavgrndv8qi3"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (ashiftrt:V8QI
- (plus:V8QI (plus:V8QI
- (match_operand:V8QI 1 "register_operand" "y")
- (match_operand:V8QI 2 "register_operand" "y"))
- (const_vector:V8QI [(const_int 1)
- (const_int 1)
- (const_int 1)
- (const_int 1)
- (const_int 1)
- (const_int 1)
- (const_int 1)
- (const_int 1)]))
- (const_int 1)))]
- "TARGET_REALLY_IWMMXT"
- "wavg2br%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_uavgrndv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (ashiftrt:V4HI
- (plus:V4HI (plus:V4HI
- (match_operand:V4HI 1 "register_operand" "y")
- (match_operand:V4HI 2 "register_operand" "y"))
- (const_vector:V4HI [(const_int 1)
- (const_int 1)
- (const_int 1)
- (const_int 1)]))
- (const_int 1)))]
- "TARGET_REALLY_IWMMXT"
- "wavg2hr%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-
-(define_insn "iwmmxt_uavgv8qi3"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (ashiftrt:V8QI (plus:V8QI
- (match_operand:V8QI 1 "register_operand" "y")
- (match_operand:V8QI 2 "register_operand" "y"))
- (const_int 1)))]
- "TARGET_REALLY_IWMMXT"
- "wavg2b%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_uavgv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (ashiftrt:V4HI (plus:V4HI
- (match_operand:V4HI 1 "register_operand" "y")
- (match_operand:V4HI 2 "register_operand" "y"))
- (const_int 1)))]
- "TARGET_REALLY_IWMMXT"
- "wavg2h%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_psadbw"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (abs:V8QI (minus:V8QI (match_operand:V8QI 1 "register_operand" "y")
- (match_operand:V8QI 2 "register_operand" "y"))))]
- "TARGET_REALLY_IWMMXT"
- "psadbw%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-
-;; Insert/extract/shuffle
-
-(define_insn "iwmmxt_tinsrb"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (vec_merge:V8QI (match_operand:V8QI 1 "register_operand" "0")
- (vec_duplicate:V8QI
- (truncate:QI (match_operand:SI 2 "nonimmediate_operand" "r")))
- (match_operand:SI 3 "immediate_operand" "i")))]
- "TARGET_REALLY_IWMMXT"
- "tinsrb%?\\t%0, %2, %3"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_tinsrh"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (vec_merge:V4HI (match_operand:V4HI 1 "register_operand" "0")
- (vec_duplicate:V4HI
- (truncate:HI (match_operand:SI 2 "nonimmediate_operand" "r")))
- (match_operand:SI 3 "immediate_operand" "i")))]
- "TARGET_REALLY_IWMMXT"
- "tinsrh%?\\t%0, %2, %3"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_tinsrw"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (vec_merge:V2SI (match_operand:V2SI 1 "register_operand" "0")
- (vec_duplicate:V2SI
- (match_operand:SI 2 "nonimmediate_operand" "r"))
- (match_operand:SI 3 "immediate_operand" "i")))]
- "TARGET_REALLY_IWMMXT"
- "tinsrw%?\\t%0, %2, %3"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_textrmub"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (zero_extend:SI (vec_select:QI (match_operand:V8QI 1 "register_operand" "y")
- (parallel
- [(match_operand:SI 2 "immediate_operand" "i")]))))]
- "TARGET_REALLY_IWMMXT"
- "textrmub%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_textrmsb"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (sign_extend:SI (vec_select:QI (match_operand:V8QI 1 "register_operand" "y")
- (parallel
- [(match_operand:SI 2 "immediate_operand" "i")]))))]
- "TARGET_REALLY_IWMMXT"
- "textrmsb%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_textrmuh"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (zero_extend:SI (vec_select:HI (match_operand:V4HI 1 "register_operand" "y")
- (parallel
- [(match_operand:SI 2 "immediate_operand" "i")]))))]
- "TARGET_REALLY_IWMMXT"
- "textrmuh%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_textrmsh"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (sign_extend:SI (vec_select:HI (match_operand:V4HI 1 "register_operand" "y")
- (parallel
- [(match_operand:SI 2 "immediate_operand" "i")]))))]
- "TARGET_REALLY_IWMMXT"
- "textrmsh%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-;; There are signed/unsigned variants of this instruction, but they are
-;; pointless.
-(define_insn "iwmmxt_textrmw"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (vec_select:SI (match_operand:V2SI 1 "register_operand" "y")
- (parallel [(match_operand:SI 2 "immediate_operand" "i")])))]
- "TARGET_REALLY_IWMMXT"
- "textrmsw%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wshufh"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (unspec:V4HI [(match_operand:V4HI 1 "register_operand" "y")
- (match_operand:SI 2 "immediate_operand" "i")] UNSPEC_WSHUFH))]
- "TARGET_REALLY_IWMMXT"
- "wshufh%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-;; Mask-generating comparisons
-;;
-;; Note - you cannot use patterns like these here:
-;;
-;; (set:<vector> (match:<vector>) (<comparator>:<vector> (match:<vector>) (match:<vector>)))
-;;
-;; Because GCC will assume that the truth value (1 or 0) is installed
-;; into the entire destination vector, (with the '1' going into the least
-;; significant element of the vector). This is not how these instructions
-;; behave.
-;;
-;; Unfortunately the current patterns are illegal. They are SET insns
-;; without a SET in them. They work in most cases for ordinary code
-;; generation, but there are circumstances where they can cause gcc to fail.
-;; XXX - FIXME.
-
-(define_insn "eqv8qi3"
- [(unspec_volatile [(match_operand:V8QI 0 "register_operand" "=y")
- (match_operand:V8QI 1 "register_operand" "y")
- (match_operand:V8QI 2 "register_operand" "y")]
- VUNSPEC_WCMP_EQ)]
- "TARGET_REALLY_IWMMXT"
- "wcmpeqb%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "eqv4hi3"
- [(unspec_volatile [(match_operand:V4HI 0 "register_operand" "=y")
- (match_operand:V4HI 1 "register_operand" "y")
- (match_operand:V4HI 2 "register_operand" "y")]
- VUNSPEC_WCMP_EQ)]
- "TARGET_REALLY_IWMMXT"
- "wcmpeqh%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "eqv2si3"
- [(unspec_volatile:V2SI [(match_operand:V2SI 0 "register_operand" "=y")
- (match_operand:V2SI 1 "register_operand" "y")
- (match_operand:V2SI 2 "register_operand" "y")]
- VUNSPEC_WCMP_EQ)]
- "TARGET_REALLY_IWMMXT"
- "wcmpeqw%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "gtuv8qi3"
- [(unspec_volatile [(match_operand:V8QI 0 "register_operand" "=y")
- (match_operand:V8QI 1 "register_operand" "y")
- (match_operand:V8QI 2 "register_operand" "y")]
- VUNSPEC_WCMP_GTU)]
- "TARGET_REALLY_IWMMXT"
- "wcmpgtub%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "gtuv4hi3"
- [(unspec_volatile [(match_operand:V4HI 0 "register_operand" "=y")
- (match_operand:V4HI 1 "register_operand" "y")
- (match_operand:V4HI 2 "register_operand" "y")]
- VUNSPEC_WCMP_GTU)]
- "TARGET_REALLY_IWMMXT"
- "wcmpgtuh%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "gtuv2si3"
- [(unspec_volatile [(match_operand:V2SI 0 "register_operand" "=y")
- (match_operand:V2SI 1 "register_operand" "y")
- (match_operand:V2SI 2 "register_operand" "y")]
- VUNSPEC_WCMP_GTU)]
- "TARGET_REALLY_IWMMXT"
- "wcmpgtuw%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "gtv8qi3"
- [(unspec_volatile [(match_operand:V8QI 0 "register_operand" "=y")
- (match_operand:V8QI 1 "register_operand" "y")
- (match_operand:V8QI 2 "register_operand" "y")]
- VUNSPEC_WCMP_GT)]
- "TARGET_REALLY_IWMMXT"
- "wcmpgtsb%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "gtv4hi3"
- [(unspec_volatile [(match_operand:V4HI 0 "register_operand" "=y")
- (match_operand:V4HI 1 "register_operand" "y")
- (match_operand:V4HI 2 "register_operand" "y")]
- VUNSPEC_WCMP_GT)]
- "TARGET_REALLY_IWMMXT"
- "wcmpgtsh%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "gtv2si3"
- [(unspec_volatile [(match_operand:V2SI 0 "register_operand" "=y")
- (match_operand:V2SI 1 "register_operand" "y")
- (match_operand:V2SI 2 "register_operand" "y")]
- VUNSPEC_WCMP_GT)]
- "TARGET_REALLY_IWMMXT"
- "wcmpgtsw%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-;; Max/min insns
-
-(define_insn "smaxv8qi3"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (smax:V8QI (match_operand:V8QI 1 "register_operand" "y")
- (match_operand:V8QI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wmaxsb%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "umaxv8qi3"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (umax:V8QI (match_operand:V8QI 1 "register_operand" "y")
- (match_operand:V8QI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wmaxub%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "smaxv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (smax:V4HI (match_operand:V4HI 1 "register_operand" "y")
- (match_operand:V4HI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wmaxsh%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "umaxv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (umax:V4HI (match_operand:V4HI 1 "register_operand" "y")
- (match_operand:V4HI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wmaxuh%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "smaxv2si3"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (smax:V2SI (match_operand:V2SI 1 "register_operand" "y")
- (match_operand:V2SI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wmaxsw%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "umaxv2si3"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (umax:V2SI (match_operand:V2SI 1 "register_operand" "y")
- (match_operand:V2SI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wmaxuw%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "sminv8qi3"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (smin:V8QI (match_operand:V8QI 1 "register_operand" "y")
- (match_operand:V8QI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wminsb%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "uminv8qi3"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (umin:V8QI (match_operand:V8QI 1 "register_operand" "y")
- (match_operand:V8QI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wminub%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "sminv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (smin:V4HI (match_operand:V4HI 1 "register_operand" "y")
- (match_operand:V4HI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wminsh%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "uminv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (umin:V4HI (match_operand:V4HI 1 "register_operand" "y")
- (match_operand:V4HI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wminuh%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "sminv2si3"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (smin:V2SI (match_operand:V2SI 1 "register_operand" "y")
- (match_operand:V2SI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wminsw%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "uminv2si3"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (umin:V2SI (match_operand:V2SI 1 "register_operand" "y")
- (match_operand:V2SI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wminuw%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-;; Pack/unpack insns.
-
-(define_insn "iwmmxt_wpackhss"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (vec_concat:V8QI
- (ss_truncate:V4QI (match_operand:V4HI 1 "register_operand" "y"))
- (ss_truncate:V4QI (match_operand:V4HI 2 "register_operand" "y"))))]
- "TARGET_REALLY_IWMMXT"
- "wpackhss%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wpackwss"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (vec_concat:V4HI
- (ss_truncate:V2HI (match_operand:V2SI 1 "register_operand" "y"))
- (ss_truncate:V2HI (match_operand:V2SI 2 "register_operand" "y"))))]
- "TARGET_REALLY_IWMMXT"
- "wpackwss%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wpackdss"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (vec_concat:V2SI
- (ss_truncate:SI (match_operand:DI 1 "register_operand" "y"))
- (ss_truncate:SI (match_operand:DI 2 "register_operand" "y"))))]
- "TARGET_REALLY_IWMMXT"
- "wpackdss%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wpackhus"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (vec_concat:V8QI
- (us_truncate:V4QI (match_operand:V4HI 1 "register_operand" "y"))
- (us_truncate:V4QI (match_operand:V4HI 2 "register_operand" "y"))))]
- "TARGET_REALLY_IWMMXT"
- "wpackhus%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wpackwus"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (vec_concat:V4HI
- (us_truncate:V2HI (match_operand:V2SI 1 "register_operand" "y"))
- (us_truncate:V2HI (match_operand:V2SI 2 "register_operand" "y"))))]
- "TARGET_REALLY_IWMMXT"
- "wpackwus%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wpackdus"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (vec_concat:V2SI
- (us_truncate:SI (match_operand:DI 1 "register_operand" "y"))
- (us_truncate:SI (match_operand:DI 2 "register_operand" "y"))))]
- "TARGET_REALLY_IWMMXT"
- "wpackdus%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-
-(define_insn "iwmmxt_wunpckihb"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (vec_merge:V8QI
- (vec_select:V8QI (match_operand:V8QI 1 "register_operand" "y")
- (parallel [(const_int 4)
- (const_int 0)
- (const_int 5)
- (const_int 1)
- (const_int 6)
- (const_int 2)
- (const_int 7)
- (const_int 3)]))
- (vec_select:V8QI (match_operand:V8QI 2 "register_operand" "y")
- (parallel [(const_int 0)
- (const_int 4)
- (const_int 1)
- (const_int 5)
- (const_int 2)
- (const_int 6)
- (const_int 3)
- (const_int 7)]))
- (const_int 85)))]
- "TARGET_REALLY_IWMMXT"
- "wunpckihb%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wunpckihh"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (vec_merge:V4HI
- (vec_select:V4HI (match_operand:V4HI 1 "register_operand" "y")
- (parallel [(const_int 0)
- (const_int 2)
- (const_int 1)
- (const_int 3)]))
- (vec_select:V4HI (match_operand:V4HI 2 "register_operand" "y")
- (parallel [(const_int 2)
- (const_int 0)
- (const_int 3)
- (const_int 1)]))
- (const_int 5)))]
- "TARGET_REALLY_IWMMXT"
- "wunpckihh%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wunpckihw"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (vec_merge:V2SI
- (vec_select:V2SI (match_operand:V2SI 1 "register_operand" "y")
- (parallel [(const_int 0)
- (const_int 1)]))
- (vec_select:V2SI (match_operand:V2SI 2 "register_operand" "y")
- (parallel [(const_int 1)
- (const_int 0)]))
- (const_int 1)))]
- "TARGET_REALLY_IWMMXT"
- "wunpckihw%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wunpckilb"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (vec_merge:V8QI
- (vec_select:V8QI (match_operand:V8QI 1 "register_operand" "y")
- (parallel [(const_int 0)
- (const_int 4)
- (const_int 1)
- (const_int 5)
- (const_int 2)
- (const_int 6)
- (const_int 3)
- (const_int 7)]))
- (vec_select:V8QI (match_operand:V8QI 2 "register_operand" "y")
- (parallel [(const_int 4)
- (const_int 0)
- (const_int 5)
- (const_int 1)
- (const_int 6)
- (const_int 2)
- (const_int 7)
- (const_int 3)]))
- (const_int 85)))]
- "TARGET_REALLY_IWMMXT"
- "wunpckilb%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wunpckilh"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (vec_merge:V4HI
- (vec_select:V4HI (match_operand:V4HI 1 "register_operand" "y")
- (parallel [(const_int 2)
- (const_int 0)
- (const_int 3)
- (const_int 1)]))
- (vec_select:V4HI (match_operand:V4HI 2 "register_operand" "y")
- (parallel [(const_int 0)
- (const_int 2)
- (const_int 1)
- (const_int 3)]))
- (const_int 5)))]
- "TARGET_REALLY_IWMMXT"
- "wunpckilh%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wunpckilw"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (vec_merge:V2SI
- (vec_select:V2SI (match_operand:V2SI 1 "register_operand" "y")
- (parallel [(const_int 1)
- (const_int 0)]))
- (vec_select:V2SI (match_operand:V2SI 2 "register_operand" "y")
- (parallel [(const_int 0)
- (const_int 1)]))
- (const_int 1)))]
- "TARGET_REALLY_IWMMXT"
- "wunpckilw%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wunpckehub"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (zero_extend:V4HI
- (vec_select:V4QI (match_operand:V8QI 1 "register_operand" "y")
- (parallel [(const_int 4) (const_int 5)
- (const_int 6) (const_int 7)]))))]
- "TARGET_REALLY_IWMMXT"
- "wunpckehub%?\\t%0, %1"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wunpckehuh"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (zero_extend:V2SI
- (vec_select:V2HI (match_operand:V4HI 1 "register_operand" "y")
- (parallel [(const_int 2) (const_int 3)]))))]
- "TARGET_REALLY_IWMMXT"
- "wunpckehuh%?\\t%0, %1"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wunpckehuw"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (zero_extend:DI
- (vec_select:SI (match_operand:V2SI 1 "register_operand" "y")
- (parallel [(const_int 1)]))))]
- "TARGET_REALLY_IWMMXT"
- "wunpckehuw%?\\t%0, %1"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wunpckehsb"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (sign_extend:V4HI
- (vec_select:V4QI (match_operand:V8QI 1 "register_operand" "y")
- (parallel [(const_int 4) (const_int 5)
- (const_int 6) (const_int 7)]))))]
- "TARGET_REALLY_IWMMXT"
- "wunpckehsb%?\\t%0, %1"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wunpckehsh"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (sign_extend:V2SI
- (vec_select:V2HI (match_operand:V4HI 1 "register_operand" "y")
- (parallel [(const_int 2) (const_int 3)]))))]
- "TARGET_REALLY_IWMMXT"
- "wunpckehsh%?\\t%0, %1"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wunpckehsw"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (sign_extend:DI
- (vec_select:SI (match_operand:V2SI 1 "register_operand" "y")
- (parallel [(const_int 1)]))))]
- "TARGET_REALLY_IWMMXT"
- "wunpckehsw%?\\t%0, %1"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wunpckelub"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (zero_extend:V4HI
- (vec_select:V4QI (match_operand:V8QI 1 "register_operand" "y")
- (parallel [(const_int 0) (const_int 1)
- (const_int 2) (const_int 3)]))))]
- "TARGET_REALLY_IWMMXT"
- "wunpckelub%?\\t%0, %1"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wunpckeluh"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (zero_extend:V2SI
- (vec_select:V2HI (match_operand:V4HI 1 "register_operand" "y")
- (parallel [(const_int 0) (const_int 1)]))))]
- "TARGET_REALLY_IWMMXT"
- "wunpckeluh%?\\t%0, %1"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wunpckeluw"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (zero_extend:DI
- (vec_select:SI (match_operand:V2SI 1 "register_operand" "y")
- (parallel [(const_int 0)]))))]
- "TARGET_REALLY_IWMMXT"
- "wunpckeluw%?\\t%0, %1"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wunpckelsb"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (sign_extend:V4HI
- (vec_select:V4QI (match_operand:V8QI 1 "register_operand" "y")
- (parallel [(const_int 0) (const_int 1)
- (const_int 2) (const_int 3)]))))]
- "TARGET_REALLY_IWMMXT"
- "wunpckelsb%?\\t%0, %1"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wunpckelsh"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (sign_extend:V2SI
- (vec_select:V2HI (match_operand:V4HI 1 "register_operand" "y")
- (parallel [(const_int 0) (const_int 1)]))))]
- "TARGET_REALLY_IWMMXT"
- "wunpckelsh%?\\t%0, %1"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wunpckelsw"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (sign_extend:DI
- (vec_select:SI (match_operand:V2SI 1 "register_operand" "y")
- (parallel [(const_int 0)]))))]
- "TARGET_REALLY_IWMMXT"
- "wunpckelsw%?\\t%0, %1"
- [(set_attr "predicable" "yes")])
-
-;; Shifts
-
-(define_insn "rorv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (rotatert:V4HI (match_operand:V4HI 1 "register_operand" "y")
- (match_operand:SI 2 "register_operand" "z")))]
- "TARGET_REALLY_IWMMXT"
- "wrorhg%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "rorv2si3"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (rotatert:V2SI (match_operand:V2SI 1 "register_operand" "y")
- (match_operand:SI 2 "register_operand" "z")))]
- "TARGET_REALLY_IWMMXT"
- "wrorwg%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "rordi3"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (rotatert:DI (match_operand:DI 1 "register_operand" "y")
- (match_operand:SI 2 "register_operand" "z")))]
- "TARGET_REALLY_IWMMXT"
- "wrordg%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "ashrv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (ashiftrt:V4HI (match_operand:V4HI 1 "register_operand" "y")
- (match_operand:SI 2 "register_operand" "z")))]
- "TARGET_REALLY_IWMMXT"
- "wsrahg%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "ashrv2si3"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (ashiftrt:V2SI (match_operand:V2SI 1 "register_operand" "y")
- (match_operand:SI 2 "register_operand" "z")))]
- "TARGET_REALLY_IWMMXT"
- "wsrawg%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "ashrdi3_iwmmxt"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (ashiftrt:DI (match_operand:DI 1 "register_operand" "y")
- (match_operand:SI 2 "register_operand" "z")))]
- "TARGET_REALLY_IWMMXT"
- "wsradg%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "lshrv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (lshiftrt:V4HI (match_operand:V4HI 1 "register_operand" "y")
- (match_operand:SI 2 "register_operand" "z")))]
- "TARGET_REALLY_IWMMXT"
- "wsrlhg%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "lshrv2si3"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (lshiftrt:V2SI (match_operand:V2SI 1 "register_operand" "y")
- (match_operand:SI 2 "register_operand" "z")))]
- "TARGET_REALLY_IWMMXT"
- "wsrlwg%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "lshrdi3_iwmmxt"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (lshiftrt:DI (match_operand:DI 1 "register_operand" "y")
- (match_operand:SI 2 "register_operand" "z")))]
- "TARGET_REALLY_IWMMXT"
- "wsrldg%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "ashlv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (ashift:V4HI (match_operand:V4HI 1 "register_operand" "y")
- (match_operand:SI 2 "register_operand" "z")))]
- "TARGET_REALLY_IWMMXT"
- "wsllhg%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "ashlv2si3"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (ashift:V2SI (match_operand:V2SI 1 "register_operand" "y")
- (match_operand:SI 2 "register_operand" "z")))]
- "TARGET_REALLY_IWMMXT"
- "wsllwg%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "ashldi3_iwmmxt"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (ashift:DI (match_operand:DI 1 "register_operand" "y")
- (match_operand:SI 2 "register_operand" "z")))]
- "TARGET_REALLY_IWMMXT"
- "wslldg%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "rorv4hi3_di"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (rotatert:V4HI (match_operand:V4HI 1 "register_operand" "y")
- (match_operand:DI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wrorh%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "rorv2si3_di"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (rotatert:V2SI (match_operand:V2SI 1 "register_operand" "y")
- (match_operand:DI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wrorw%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "rordi3_di"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (rotatert:DI (match_operand:DI 1 "register_operand" "y")
- (match_operand:DI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wrord%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "ashrv4hi3_di"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (ashiftrt:V4HI (match_operand:V4HI 1 "register_operand" "y")
- (match_operand:DI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wsrah%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "ashrv2si3_di"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (ashiftrt:V2SI (match_operand:V2SI 1 "register_operand" "y")
- (match_operand:DI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wsraw%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "ashrdi3_di"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (ashiftrt:DI (match_operand:DI 1 "register_operand" "y")
- (match_operand:DI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wsrad%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "lshrv4hi3_di"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (lshiftrt:V4HI (match_operand:V4HI 1 "register_operand" "y")
- (match_operand:DI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wsrlh%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "lshrv2si3_di"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (lshiftrt:V2SI (match_operand:V2SI 1 "register_operand" "y")
- (match_operand:DI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wsrlw%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "lshrdi3_di"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (lshiftrt:DI (match_operand:DI 1 "register_operand" "y")
- (match_operand:DI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wsrld%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "ashlv4hi3_di"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (ashift:V4HI (match_operand:V4HI 1 "register_operand" "y")
- (match_operand:DI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wsllh%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "ashlv2si3_di"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (ashift:V2SI (match_operand:V2SI 1 "register_operand" "y")
- (match_operand:DI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wsllw%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "ashldi3_di"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (ashift:DI (match_operand:DI 1 "register_operand" "y")
- (match_operand:DI 2 "register_operand" "y")))]
- "TARGET_REALLY_IWMMXT"
- "wslld%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wmadds"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (unspec:V4HI [(match_operand:V4HI 1 "register_operand" "y")
- (match_operand:V4HI 2 "register_operand" "y")] UNSPEC_WMADDS))]
- "TARGET_REALLY_IWMMXT"
- "wmadds%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wmaddu"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (unspec:V4HI [(match_operand:V4HI 1 "register_operand" "y")
- (match_operand:V4HI 2 "register_operand" "y")] UNSPEC_WMADDU))]
- "TARGET_REALLY_IWMMXT"
- "wmaddu%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_tmia"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (plus:DI (match_operand:DI 1 "register_operand" "0")
- (mult:DI (sign_extend:DI
- (match_operand:SI 2 "register_operand" "r"))
- (sign_extend:DI
- (match_operand:SI 3 "register_operand" "r")))))]
- "TARGET_REALLY_IWMMXT"
- "tmia%?\\t%0, %2, %3"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_tmiaph"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (plus:DI (match_operand:DI 1 "register_operand" "0")
- (plus:DI
- (mult:DI (sign_extend:DI
- (truncate:HI (match_operand:SI 2 "register_operand" "r")))
- (sign_extend:DI
- (truncate:HI (match_operand:SI 3 "register_operand" "r"))))
- (mult:DI (sign_extend:DI
- (truncate:HI (ashiftrt:SI (match_dup 2) (const_int 16))))
- (sign_extend:DI
- (truncate:HI (ashiftrt:SI (match_dup 3) (const_int 16))))))))]
- "TARGET_REALLY_IWMMXT"
- "tmiaph%?\\t%0, %2, %3"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_tmiabb"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (plus:DI (match_operand:DI 1 "register_operand" "0")
- (mult:DI (sign_extend:DI
- (truncate:HI (match_operand:SI 2 "register_operand" "r")))
- (sign_extend:DI
- (truncate:HI (match_operand:SI 3 "register_operand" "r"))))))]
- "TARGET_REALLY_IWMMXT"
- "tmiabb%?\\t%0, %2, %3"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_tmiatb"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (plus:DI (match_operand:DI 1 "register_operand" "0")
- (mult:DI (sign_extend:DI
- (truncate:HI (ashiftrt:SI
- (match_operand:SI 2 "register_operand" "r")
- (const_int 16))))
- (sign_extend:DI
- (truncate:HI (match_operand:SI 3 "register_operand" "r"))))))]
- "TARGET_REALLY_IWMMXT"
- "tmiatb%?\\t%0, %2, %3"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_tmiabt"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (plus:DI (match_operand:DI 1 "register_operand" "0")
- (mult:DI (sign_extend:DI
- (truncate:HI (match_operand:SI 2 "register_operand" "r")))
- (sign_extend:DI
- (truncate:HI (ashiftrt:SI
- (match_operand:SI 3 "register_operand" "r")
- (const_int 16)))))))]
- "TARGET_REALLY_IWMMXT"
- "tmiabt%?\\t%0, %2, %3"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_tmiatt"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (plus:DI (match_operand:DI 1 "register_operand" "0")
- (mult:DI (sign_extend:DI
- (truncate:HI (ashiftrt:SI
- (match_operand:SI 2 "register_operand" "r")
- (const_int 16))))
- (sign_extend:DI
- (truncate:HI (ashiftrt:SI
- (match_operand:SI 3 "register_operand" "r")
- (const_int 16)))))))]
- "TARGET_REALLY_IWMMXT"
- "tmiatt%?\\t%0, %2, %3"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_tbcstqi"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (vec_duplicate:V8QI (match_operand:QI 1 "register_operand" "r")))]
- "TARGET_REALLY_IWMMXT"
- "tbcstb%?\\t%0, %1"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_tbcsthi"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (vec_duplicate:V4HI (match_operand:HI 1 "register_operand" "r")))]
- "TARGET_REALLY_IWMMXT"
- "tbcsth%?\\t%0, %1"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_tbcstsi"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (vec_duplicate:V2SI (match_operand:SI 1 "register_operand" "r")))]
- "TARGET_REALLY_IWMMXT"
- "tbcstw%?\\t%0, %1"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_tmovmskb"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(match_operand:V8QI 1 "register_operand" "y")] UNSPEC_TMOVMSK))]
- "TARGET_REALLY_IWMMXT"
- "tmovmskb%?\\t%0, %1"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_tmovmskh"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(match_operand:V4HI 1 "register_operand" "y")] UNSPEC_TMOVMSK))]
- "TARGET_REALLY_IWMMXT"
- "tmovmskh%?\\t%0, %1"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_tmovmskw"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(match_operand:V2SI 1 "register_operand" "y")] UNSPEC_TMOVMSK))]
- "TARGET_REALLY_IWMMXT"
- "tmovmskw%?\\t%0, %1"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_waccb"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (unspec:DI [(match_operand:V8QI 1 "register_operand" "y")] UNSPEC_WACC))]
- "TARGET_REALLY_IWMMXT"
- "waccb%?\\t%0, %1"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wacch"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (unspec:DI [(match_operand:V4HI 1 "register_operand" "y")] UNSPEC_WACC))]
- "TARGET_REALLY_IWMMXT"
- "wacch%?\\t%0, %1"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_waccw"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (unspec:DI [(match_operand:V2SI 1 "register_operand" "y")] UNSPEC_WACC))]
- "TARGET_REALLY_IWMMXT"
- "waccw%?\\t%0, %1"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_walign"
- [(set (match_operand:V8QI 0 "register_operand" "=y,y")
- (subreg:V8QI (ashiftrt:TI
- (subreg:TI (vec_concat:V16QI
- (match_operand:V8QI 1 "register_operand" "y,y")
- (match_operand:V8QI 2 "register_operand" "y,y")) 0)
- (mult:SI
- (match_operand:SI 3 "nonmemory_operand" "i,z")
- (const_int 8))) 0))]
- "TARGET_REALLY_IWMMXT"
- "@
- waligni%?\\t%0, %1, %2, %3
- walignr%U3%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_tmrc"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")]
- VUNSPEC_TMRC))]
- "TARGET_REALLY_IWMMXT"
- "tmrc%?\\t%0, %w1"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_tmcr"
- [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")
- (match_operand:SI 1 "register_operand" "r")]
- VUNSPEC_TMCR)]
- "TARGET_REALLY_IWMMXT"
- "tmcr%?\\t%w0, %1"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wsadb"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (unspec:V8QI [(match_operand:V8QI 1 "register_operand" "y")
- (match_operand:V8QI 2 "register_operand" "y")] UNSPEC_WSAD))]
- "TARGET_REALLY_IWMMXT"
- "wsadb%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wsadh"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (unspec:V4HI [(match_operand:V4HI 1 "register_operand" "y")
- (match_operand:V4HI 2 "register_operand" "y")] UNSPEC_WSAD))]
- "TARGET_REALLY_IWMMXT"
- "wsadh%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wsadbz"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (unspec:V8QI [(match_operand:V8QI 1 "register_operand" "y")
- (match_operand:V8QI 2 "register_operand" "y")] UNSPEC_WSADZ))]
- "TARGET_REALLY_IWMMXT"
- "wsadbz%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
-(define_insn "iwmmxt_wsadhz"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (unspec:V4HI [(match_operand:V4HI 1 "register_operand" "y")
- (match_operand:V4HI 2 "register_operand" "y")] UNSPEC_WSADZ))]
- "TARGET_REALLY_IWMMXT"
- "wsadhz%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")])
-
diff --git a/gcc-4.2.1/gcc/config/arm/kaos-arm.h b/gcc-4.2.1/gcc/config/arm/kaos-arm.h
deleted file mode 100644
index b575489b1..000000000
--- a/gcc-4.2.1/gcc/config/arm/kaos-arm.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* Definitions of target machine for GNU compiler.
- kaOS on arm architecture version.
- Copyright (C) 2003 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
-
-#undef TARGET_VERSION
-#define TARGET_VERSION fputs (" (ARM/kaOS[ELF])", stderr);
-
diff --git a/gcc-4.2.1/gcc/config/arm/kaos-strongarm.h b/gcc-4.2.1/gcc/config/arm/kaos-strongarm.h
deleted file mode 100644
index 7be215199..000000000
--- a/gcc-4.2.1/gcc/config/arm/kaos-strongarm.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* Definitions of target machine for GNU compiler.
- kaOS on strongarm architecture version.
- Copyright (C) 2003 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
-
-#undef TARGET_VERSION
-#define TARGET_VERSION fputs (" (StrongARM/kaOS[ELF])", stderr);
-
diff --git a/gcc-4.2.1/gcc/config/arm/lib1funcs.asm b/gcc-4.2.1/gcc/config/arm/lib1funcs.asm
deleted file mode 100644
index 7e0831ade..000000000
--- a/gcc-4.2.1/gcc/config/arm/lib1funcs.asm
+++ /dev/null
@@ -1,1392 +0,0 @@
-@ libgcc routines for ARM cpu.
-@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
-
-/* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005
- 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 into combinations with other programs,
-and to distribute those combinations 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 a combine
-executable.)
-
-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, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
-
-/* An executable stack is *not* required for these functions. */
-#if defined(__ELF__) && defined(__linux__)
-.section .note.GNU-stack,"",%progbits
-.previous
-#endif
-
-/* ------------------------------------------------------------------------ */
-
-/* We need to know what prefix to add to function names. */
-
-#ifndef __USER_LABEL_PREFIX__
-#error __USER_LABEL_PREFIX__ not defined
-#endif
-
-/* ANSI concatenation macros. */
-
-#define CONCAT1(a, b) CONCAT2(a, b)
-#define CONCAT2(a, b) a ## b
-
-/* Use the right prefix for global labels. */
-
-#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
-
-#ifdef __ELF__
-#ifdef __thumb__
-#define __PLT__ /* Not supported in Thumb assembler (for now). */
-#else
-#define __PLT__ (PLT)
-#endif
-#define TYPE(x) .type SYM(x),function
-#define SIZE(x) .size SYM(x), . - SYM(x)
-#define LSYM(x) .x
-#else
-#define __PLT__
-#define TYPE(x)
-#define SIZE(x)
-#define LSYM(x) x
-#endif
-
-/* Function end macros. Variants for interworking. */
-
-@ This selects the minimum architecture level required.
-#define __ARM_ARCH__ 3
-
-#if defined(__ARM_ARCH_3M__) || defined(__ARM_ARCH_4__) \
- || defined(__ARM_ARCH_4T__)
-/* We use __ARM_ARCH__ set to 4 here, but in reality it's any processor with
- long multiply instructions. That includes v3M. */
-# undef __ARM_ARCH__
-# define __ARM_ARCH__ 4
-#endif
-
-#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
- || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
- || defined(__ARM_ARCH_5TEJ__)
-# undef __ARM_ARCH__
-# define __ARM_ARCH__ 5
-#endif
-
-#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
- || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
- || defined(__ARM_ARCH_6ZK__)
-# undef __ARM_ARCH__
-# define __ARM_ARCH__ 6
-#endif
-
-#ifndef __ARM_ARCH__
-#error Unable to determine architecture.
-#endif
-
-/* How to return from a function call depends on the architecture variant. */
-
-#if (__ARM_ARCH__ > 4) || defined(__ARM_ARCH_4T__)
-
-# define RET bx lr
-# define RETc(x) bx##x lr
-
-/* Special precautions for interworking on armv4t. */
-# if (__ARM_ARCH__ == 4)
-
-/* Always use bx, not ldr pc. */
-# if (defined(__thumb__) || defined(__THUMB_INTERWORK__))
-# define __INTERWORKING__
-# endif /* __THUMB__ || __THUMB_INTERWORK__ */
-
-/* Include thumb stub before arm mode code. */
-# if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
-# define __INTERWORKING_STUBS__
-# endif /* __thumb__ && !__THUMB_INTERWORK__ */
-
-#endif /* __ARM_ARCH == 4 */
-
-#else
-
-# define RET mov pc, lr
-# define RETc(x) mov##x pc, lr
-
-#endif
-
-.macro cfi_pop advance, reg, cfa_offset
-#ifdef __ELF__
- .pushsection .debug_frame
- .byte 0x4 /* DW_CFA_advance_loc4 */
- .4byte \advance
- .byte (0xc0 | \reg) /* DW_CFA_restore */
- .byte 0xe /* DW_CFA_def_cfa_offset */
- .uleb128 \cfa_offset
- .popsection
-#endif
-.endm
-.macro cfi_push advance, reg, offset, cfa_offset
-#ifdef __ELF__
- .pushsection .debug_frame
- .byte 0x4 /* DW_CFA_advance_loc4 */
- .4byte \advance
- .byte (0x80 | \reg) /* DW_CFA_offset */
- .uleb128 (\offset / -4)
- .byte 0xe /* DW_CFA_def_cfa_offset */
- .uleb128 \cfa_offset
- .popsection
-#endif
-.endm
-.macro cfi_start start_label, end_label
-#ifdef __ELF__
- .pushsection .debug_frame
-LSYM(Lstart_frame):
- .4byte LSYM(Lend_cie) - LSYM(Lstart_cie) @ Length of CIE
-LSYM(Lstart_cie):
- .4byte 0xffffffff @ CIE Identifier Tag
- .byte 0x1 @ CIE Version
- .ascii "\0" @ CIE Augmentation
- .uleb128 0x1 @ CIE Code Alignment Factor
- .sleb128 -4 @ CIE Data Alignment Factor
- .byte 0xe @ CIE RA Column
- .byte 0xc @ DW_CFA_def_cfa
- .uleb128 0xd
- .uleb128 0x0
-
- .align 2
-LSYM(Lend_cie):
- .4byte LSYM(Lend_fde)-LSYM(Lstart_fde) @ FDE Length
-LSYM(Lstart_fde):
- .4byte LSYM(Lstart_frame) @ FDE CIE offset
- .4byte \start_label @ FDE initial location
- .4byte \end_label-\start_label @ FDE address range
- .popsection
-#endif
-.endm
-.macro cfi_end end_label
-#ifdef __ELF__
- .pushsection .debug_frame
- .align 2
-LSYM(Lend_fde):
- .popsection
-\end_label:
-#endif
-.endm
-
-/* Don't pass dirn, it's there just to get token pasting right. */
-
-.macro RETLDM regs=, cond=, unwind=, dirn=ia
-#if defined (__INTERWORKING__)
- .ifc "\regs",""
- ldr\cond lr, [sp], #8
- .else
- ldm\cond\dirn sp!, {\regs, lr}
- .endif
- .ifnc "\unwind", ""
- /* Mark LR as restored. */
-97: cfi_pop 97b - \unwind, 0xe, 0x0
- .endif
- bx\cond lr
-#else
- .ifc "\regs",""
- ldr\cond pc, [sp], #8
- .else
- ldm\cond\dirn sp!, {\regs, pc}
- .endif
-#endif
-.endm
-
-
-.macro ARM_LDIV0 name
- str lr, [sp, #-8]!
-98: cfi_push 98b - __\name, 0xe, -0x8, 0x8
- bl SYM (__div0) __PLT__
- mov r0, #0 @ About as wrong as it could be.
- RETLDM unwind=98b
-.endm
-
-
-.macro THUMB_LDIV0 name
- push { r1, lr }
-98: cfi_push 98b - __\name, 0xe, -0x4, 0x8
- bl SYM (__div0)
- mov r0, #0 @ About as wrong as it could be.
-#if defined (__INTERWORKING__)
- pop { r1, r2 }
- bx r2
-#else
- pop { r1, pc }
-#endif
-.endm
-
-.macro FUNC_END name
- SIZE (__\name)
-.endm
-
-.macro DIV_FUNC_END name
- cfi_start __\name, LSYM(Lend_div0)
-LSYM(Ldiv0):
-#ifdef __thumb__
- THUMB_LDIV0 \name
-#else
- ARM_LDIV0 \name
-#endif
- cfi_end LSYM(Lend_div0)
- FUNC_END \name
-.endm
-
-.macro THUMB_FUNC_START name
- .globl SYM (\name)
- TYPE (\name)
- .thumb_func
-SYM (\name):
-.endm
-
-/* Function start macros. Variants for ARM and Thumb. */
-
-#ifdef __thumb__
-#define THUMB_FUNC .thumb_func
-#define THUMB_CODE .force_thumb
-#else
-#define THUMB_FUNC
-#define THUMB_CODE
-#endif
-
-.macro FUNC_START name
- .text
- .globl SYM (__\name)
- TYPE (__\name)
- .align 0
- THUMB_CODE
- THUMB_FUNC
-SYM (__\name):
-.endm
-
-/* Special function that will always be coded in ARM assembly, even if
- in Thumb-only compilation. */
-
-#if defined(__INTERWORKING_STUBS__)
-.macro ARM_FUNC_START name
- FUNC_START \name
- bx pc
- nop
- .arm
-/* A hook to tell gdb that we've switched to ARM mode. Also used to call
- directly from other local arm routines. */
-_L__\name:
-.endm
-#define EQUIV .thumb_set
-/* Branch directly to a function declared with ARM_FUNC_START.
- Must be called in arm mode. */
-.macro ARM_CALL name
- bl _L__\name
-.endm
-#else
-.macro ARM_FUNC_START name
- .text
- .globl SYM (__\name)
- TYPE (__\name)
- .align 0
- .arm
-SYM (__\name):
-.endm
-#define EQUIV .set
-.macro ARM_CALL name
- bl __\name
-.endm
-#endif
-
-.macro FUNC_ALIAS new old
- .globl SYM (__\new)
-#if defined (__thumb__)
- .thumb_set SYM (__\new), SYM (__\old)
-#else
- .set SYM (__\new), SYM (__\old)
-#endif
-.endm
-
-.macro ARM_FUNC_ALIAS new old
- .globl SYM (__\new)
- EQUIV SYM (__\new), SYM (__\old)
-#if defined(__INTERWORKING_STUBS__)
- .set SYM (_L__\new), SYM (_L__\old)
-#endif
-.endm
-
-#ifdef __ARMEB__
-#define xxh r0
-#define xxl r1
-#define yyh r2
-#define yyl r3
-#else
-#define xxh r1
-#define xxl r0
-#define yyh r3
-#define yyl r2
-#endif
-
-#ifdef __thumb__
-/* Register aliases. */
-
-work .req r4 @ XXXX is this safe ?
-dividend .req r0
-divisor .req r1
-overdone .req r2
-result .req r2
-curbit .req r3
-#endif
-#if 0
-ip .req r12
-sp .req r13
-lr .req r14
-pc .req r15
-#endif
-
-/* ------------------------------------------------------------------------ */
-/* Bodies of the division and modulo routines. */
-/* ------------------------------------------------------------------------ */
-.macro ARM_DIV_BODY dividend, divisor, result, curbit
-
-#if __ARM_ARCH__ >= 5 && ! defined (__OPTIMIZE_SIZE__)
-
- clz \curbit, \dividend
- clz \result, \divisor
- sub \curbit, \result, \curbit
- rsbs \curbit, \curbit, #31
- addne \curbit, \curbit, \curbit, lsl #1
- mov \result, #0
- addne pc, pc, \curbit, lsl #2
- nop
- .set shift, 32
- .rept 32
- .set shift, shift - 1
- cmp \dividend, \divisor, lsl #shift
- adc \result, \result, \result
- subcs \dividend, \dividend, \divisor, lsl #shift
- .endr
-
-#else /* __ARM_ARCH__ < 5 || defined (__OPTIMIZE_SIZE__) */
-#if __ARM_ARCH__ >= 5
-
- clz \curbit, \divisor
- clz \result, \dividend
- sub \result, \curbit, \result
- mov \curbit, #1
- mov \divisor, \divisor, lsl \result
- mov \curbit, \curbit, lsl \result
- mov \result, #0
-
-#else /* __ARM_ARCH__ < 5 */
-
- @ Initially shift the divisor left 3 bits if possible,
- @ set curbit accordingly. This allows for curbit to be located
- @ at the left end of each 4 bit nibbles in the division loop
- @ to save one loop in most cases.
- tst \divisor, #0xe0000000
- moveq \divisor, \divisor, lsl #3
- moveq \curbit, #8
- movne \curbit, #1
-
- @ 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.
-1: cmp \divisor, #0x10000000
- cmplo \divisor, \dividend
- movlo \divisor, \divisor, lsl #4
- movlo \curbit, \curbit, lsl #4
- blo 1b
-
- @ For very big divisors, we must shift it a bit at a time, or
- @ we will be in danger of overflowing.
-1: cmp \divisor, #0x80000000
- cmplo \divisor, \dividend
- movlo \divisor, \divisor, lsl #1
- movlo \curbit, \curbit, lsl #1
- blo 1b
-
- mov \result, #0
-
-#endif /* __ARM_ARCH__ < 5 */
-
- @ Division loop
-1: cmp \dividend, \divisor
- subhs \dividend, \dividend, \divisor
- orrhs \result, \result, \curbit
- cmp \dividend, \divisor, lsr #1
- subhs \dividend, \dividend, \divisor, lsr #1
- orrhs \result, \result, \curbit, lsr #1
- cmp \dividend, \divisor, lsr #2
- subhs \dividend, \dividend, \divisor, lsr #2
- orrhs \result, \result, \curbit, lsr #2
- cmp \dividend, \divisor, lsr #3
- subhs \dividend, \dividend, \divisor, lsr #3
- orrhs \result, \result, \curbit, lsr #3
- cmp \dividend, #0 @ Early termination?
- movnes \curbit, \curbit, lsr #4 @ No, any more bits to do?
- movne \divisor, \divisor, lsr #4
- bne 1b
-
-#endif /* __ARM_ARCH__ < 5 || defined (__OPTIMIZE_SIZE__) */
-
-.endm
-/* ------------------------------------------------------------------------ */
-.macro ARM_DIV2_ORDER divisor, order
-
-#if __ARM_ARCH__ >= 5
-
- clz \order, \divisor
- rsb \order, \order, #31
-
-#else
-
- cmp \divisor, #(1 << 16)
- movhs \divisor, \divisor, lsr #16
- movhs \order, #16
- movlo \order, #0
-
- cmp \divisor, #(1 << 8)
- movhs \divisor, \divisor, lsr #8
- addhs \order, \order, #8
-
- cmp \divisor, #(1 << 4)
- movhs \divisor, \divisor, lsr #4
- addhs \order, \order, #4
-
- cmp \divisor, #(1 << 2)
- addhi \order, \order, #3
- addls \order, \order, \divisor, lsr #1
-
-#endif
-
-.endm
-/* ------------------------------------------------------------------------ */
-.macro ARM_MOD_BODY dividend, divisor, order, spare
-
-#if __ARM_ARCH__ >= 5 && ! defined (__OPTIMIZE_SIZE__)
-
- clz \order, \divisor
- clz \spare, \dividend
- sub \order, \order, \spare
- rsbs \order, \order, #31
- addne pc, pc, \order, lsl #3
- nop
- .set shift, 32
- .rept 32
- .set shift, shift - 1
- cmp \dividend, \divisor, lsl #shift
- subcs \dividend, \dividend, \divisor, lsl #shift
- .endr
-
-#else /* __ARM_ARCH__ < 5 || defined (__OPTIMIZE_SIZE__) */
-#if __ARM_ARCH__ >= 5
-
- clz \order, \divisor
- clz \spare, \dividend
- sub \order, \order, \spare
- mov \divisor, \divisor, lsl \order
-
-#else /* __ARM_ARCH__ < 5 */
-
- mov \order, #0
-
- @ 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.
-1: cmp \divisor, #0x10000000
- cmplo \divisor, \dividend
- movlo \divisor, \divisor, lsl #4
- addlo \order, \order, #4
- blo 1b
-
- @ For very big divisors, we must shift it a bit at a time, or
- @ we will be in danger of overflowing.
-1: cmp \divisor, #0x80000000
- cmplo \divisor, \dividend
- movlo \divisor, \divisor, lsl #1
- addlo \order, \order, #1
- blo 1b
-
-#endif /* __ARM_ARCH__ < 5 */
-
- @ Perform all needed substractions to keep only the reminder.
- @ Do comparisons in batch of 4 first.
- subs \order, \order, #3 @ yes, 3 is intended here
- blt 2f
-
-1: cmp \dividend, \divisor
- subhs \dividend, \dividend, \divisor
- cmp \dividend, \divisor, lsr #1
- subhs \dividend, \dividend, \divisor, lsr #1
- cmp \dividend, \divisor, lsr #2
- subhs \dividend, \dividend, \divisor, lsr #2
- cmp \dividend, \divisor, lsr #3
- subhs \dividend, \dividend, \divisor, lsr #3
- cmp \dividend, #1
- mov \divisor, \divisor, lsr #4
- subges \order, \order, #4
- bge 1b
-
- tst \order, #3
- teqne \dividend, #0
- beq 5f
-
- @ Either 1, 2 or 3 comparison/substractions are left.
-2: cmn \order, #2
- blt 4f
- beq 3f
- cmp \dividend, \divisor
- subhs \dividend, \dividend, \divisor
- mov \divisor, \divisor, lsr #1
-3: cmp \dividend, \divisor
- subhs \dividend, \dividend, \divisor
- mov \divisor, \divisor, lsr #1
-4: cmp \dividend, \divisor
- subhs \dividend, \dividend, \divisor
-5:
-
-#endif /* __ARM_ARCH__ < 5 || defined (__OPTIMIZE_SIZE__) */
-
-.endm
-/* ------------------------------------------------------------------------ */
-.macro THUMB_DIV_MOD_BODY modulo
- @ Load the constant 0x10000000 into our work register.
- mov work, #1
- lsl work, #28
-LSYM(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
- bhs LSYM(Lbignum)
- cmp divisor, dividend
- bhs LSYM(Lbignum)
- lsl divisor, #4
- lsl curbit, #4
- b LSYM(Loop1)
-LSYM(Lbignum):
- @ Set work to 0x80000000
- lsl work, #3
-LSYM(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
- bhs LSYM(Loop3)
- cmp divisor, dividend
- bhs LSYM(Loop3)
- lsl divisor, #1
- lsl curbit, #1
- b LSYM(Loop2)
-LSYM(Loop3):
- @ Test for possible subtractions ...
- .if \modulo
- @ ... 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
- blo LSYM(Lover1)
- sub dividend, dividend, divisor
-LSYM(Lover1):
- lsr work, divisor, #1
- cmp dividend, work
- blo LSYM(Lover2)
- sub dividend, dividend, work
- mov ip, curbit
- mov work, #1
- ror curbit, work
- orr overdone, curbit
- mov curbit, ip
-LSYM(Lover2):
- lsr work, divisor, #2
- cmp dividend, work
- blo LSYM(Lover3)
- sub dividend, dividend, work
- mov ip, curbit
- mov work, #2
- ror curbit, work
- orr overdone, curbit
- mov curbit, ip
-LSYM(Lover3):
- lsr work, divisor, #3
- cmp dividend, work
- blo LSYM(Lover4)
- sub dividend, dividend, work
- mov ip, curbit
- mov work, #3
- ror curbit, work
- orr overdone, curbit
- mov curbit, ip
-LSYM(Lover4):
- mov ip, curbit
- .else
- @ ... 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
- blo LSYM(Lover1)
- sub dividend, dividend, divisor
- orr result, result, curbit
-LSYM(Lover1):
- lsr work, divisor, #1
- cmp dividend, work
- blo LSYM(Lover2)
- sub dividend, dividend, work
- lsr work, curbit, #1
- orr result, work
-LSYM(Lover2):
- lsr work, divisor, #2
- cmp dividend, work
- blo LSYM(Lover3)
- sub dividend, dividend, work
- lsr work, curbit, #2
- orr result, work
-LSYM(Lover3):
- lsr work, divisor, #3
- cmp dividend, work
- blo LSYM(Lover4)
- sub dividend, dividend, work
- lsr work, curbit, #3
- orr result, work
-LSYM(Lover4):
- .endif
-
- cmp dividend, #0 @ Early termination?
- beq LSYM(Lover5)
- lsr curbit, #4 @ No, any more bits to do?
- beq LSYM(Lover5)
- lsr divisor, #4
- b LSYM(Loop3)
-LSYM(Lover5):
- .if \modulo
- @ 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.
- mov work, #0xe
- lsl work, #28
- and overdone, work
- beq LSYM(Lgot_result)
-
- @ If we terminated early, because dividend became zero, then the
- @ bit in ip will not be in the bottom nibble, and we should not
- @ perform the additions below. We must test for this though
- @ (rather relying upon the TSTs to prevent the additions) since
- @ the bit in ip could be in the top two bits which might then match
- @ with one of the smaller RORs.
- mov curbit, ip
- mov work, #0x7
- tst curbit, work
- beq LSYM(Lgot_result)
-
- mov curbit, ip
- mov work, #3
- ror curbit, work
- tst overdone, curbit
- beq LSYM(Lover6)
- lsr work, divisor, #3
- add dividend, work
-LSYM(Lover6):
- mov curbit, ip
- mov work, #2
- ror curbit, work
- tst overdone, curbit
- beq LSYM(Lover7)
- lsr work, divisor, #2
- add dividend, work
-LSYM(Lover7):
- mov curbit, ip
- mov work, #1
- ror curbit, work
- tst overdone, curbit
- beq LSYM(Lgot_result)
- lsr work, divisor, #1
- add dividend, work
- .endif
-LSYM(Lgot_result):
-.endm
-/* ------------------------------------------------------------------------ */
-/* Start of the Real Functions */
-/* ------------------------------------------------------------------------ */
-#ifdef L_udivsi3
-
- FUNC_START udivsi3
- FUNC_ALIAS aeabi_uidiv udivsi3
-
-#ifdef __thumb__
-
- cmp divisor, #0
- beq LSYM(Ldiv0)
- mov curbit, #1
- mov result, #0
-
- push { work }
- cmp dividend, divisor
- blo LSYM(Lgot_result)
-
- THUMB_DIV_MOD_BODY 0
-
- mov r0, result
- pop { work }
- RET
-
-#else /* ARM version. */
-
- subs r2, r1, #1
- RETc(eq)
- bcc LSYM(Ldiv0)
- cmp r0, r1
- bls 11f
- tst r1, r2
- beq 12f
-
- ARM_DIV_BODY r0, r1, r2, r3
-
- mov r0, r2
- RET
-
-11: moveq r0, #1
- movne r0, #0
- RET
-
-12: ARM_DIV2_ORDER r1, r2
-
- mov r0, r0, lsr r2
- RET
-
-#endif /* ARM version */
-
- DIV_FUNC_END udivsi3
-
-FUNC_START aeabi_uidivmod
-#ifdef __thumb__
- push {r0, r1, lr}
- bl SYM(__udivsi3)
- POP {r1, r2, r3}
- mul r2, r0
- sub r1, r1, r2
- bx r3
-#else
- stmfd sp!, { r0, r1, lr }
- bl SYM(__udivsi3)
- ldmfd sp!, { r1, r2, lr }
- mul r3, r2, r0
- sub r1, r1, r3
- RET
-#endif
- FUNC_END aeabi_uidivmod
-
-#endif /* L_udivsi3 */
-/* ------------------------------------------------------------------------ */
-#ifdef L_umodsi3
-
- FUNC_START umodsi3
-
-#ifdef __thumb__
-
- cmp divisor, #0
- beq LSYM(Ldiv0)
- mov curbit, #1
- cmp dividend, divisor
- bhs LSYM(Lover10)
- RET
-
-LSYM(Lover10):
- push { work }
-
- THUMB_DIV_MOD_BODY 1
-
- pop { work }
- RET
-
-#else /* ARM version. */
-
- subs r2, r1, #1 @ compare divisor with 1
- bcc LSYM(Ldiv0)
- cmpne r0, r1 @ compare dividend with divisor
- moveq r0, #0
- tsthi r1, r2 @ see if divisor is power of 2
- andeq r0, r0, r2
- RETc(ls)
-
- ARM_MOD_BODY r0, r1, r2, r3
-
- RET
-
-#endif /* ARM version. */
-
- DIV_FUNC_END umodsi3
-
-#endif /* L_umodsi3 */
-/* ------------------------------------------------------------------------ */
-#ifdef L_divsi3
-
- FUNC_START divsi3
- FUNC_ALIAS aeabi_idiv divsi3
-
-#ifdef __thumb__
- cmp divisor, #0
- beq LSYM(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 LSYM(Lover10)
- neg divisor, divisor @ Loops below use unsigned.
-LSYM(Lover10):
- cmp dividend, #0
- bpl LSYM(Lover11)
- neg dividend, dividend
-LSYM(Lover11):
- cmp dividend, divisor
- blo LSYM(Lgot_result)
-
- THUMB_DIV_MOD_BODY 0
-
- mov r0, result
- mov work, ip
- cmp work, #0
- bpl LSYM(Lover12)
- neg r0, r0
-LSYM(Lover12):
- pop { work }
- RET
-
-#else /* ARM version. */
-
- cmp r1, #0
- eor ip, r0, r1 @ save the sign of the result.
- beq LSYM(Ldiv0)
- rsbmi r1, r1, #0 @ loops below use unsigned.
- subs r2, r1, #1 @ division by 1 or -1 ?
- beq 10f
- movs r3, r0
- rsbmi r3, r0, #0 @ positive dividend value
- cmp r3, r1
- bls 11f
- tst r1, r2 @ divisor is power of 2 ?
- beq 12f
-
- ARM_DIV_BODY r3, r1, r0, r2
-
- cmp ip, #0
- rsbmi r0, r0, #0
- RET
-
-10: teq ip, r0 @ same sign ?
- rsbmi r0, r0, #0
- RET
-
-11: movlo r0, #0
- moveq r0, ip, asr #31
- orreq r0, r0, #1
- RET
-
-12: ARM_DIV2_ORDER r1, r2
-
- cmp ip, #0
- mov r0, r3, lsr r2
- rsbmi r0, r0, #0
- RET
-
-#endif /* ARM version */
-
- DIV_FUNC_END divsi3
-
-FUNC_START aeabi_idivmod
-#ifdef __thumb__
- push {r0, r1, lr}
- bl SYM(__divsi3)
- POP {r1, r2, r3}
- mul r2, r0
- sub r1, r1, r2
- bx r3
-#else
- stmfd sp!, { r0, r1, lr }
- bl SYM(__divsi3)
- ldmfd sp!, { r1, r2, lr }
- mul r3, r2, r0
- sub r1, r1, r3
- RET
-#endif
- FUNC_END aeabi_idivmod
-
-#endif /* L_divsi3 */
-/* ------------------------------------------------------------------------ */
-#ifdef L_modsi3
-
- FUNC_START modsi3
-
-#ifdef __thumb__
-
- mov curbit, #1
- cmp divisor, #0
- beq LSYM(Ldiv0)
- bpl LSYM(Lover10)
- neg divisor, divisor @ Loops below use unsigned.
-LSYM(Lover10):
- push { work }
- @ Need to save the sign of the dividend, unfortunately, we need
- @ work 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 LSYM(Lover11)
- neg dividend, dividend
-LSYM(Lover11):
- cmp dividend, divisor
- blo LSYM(Lgot_result)
-
- THUMB_DIV_MOD_BODY 1
-
- pop { work }
- cmp work, #0
- bpl LSYM(Lover12)
- neg dividend, dividend
-LSYM(Lover12):
- pop { work }
- RET
-
-#else /* ARM version. */
-
- cmp r1, #0
- beq LSYM(Ldiv0)
- rsbmi r1, r1, #0 @ loops below use unsigned.
- movs ip, r0 @ preserve sign of dividend
- rsbmi r0, r0, #0 @ if negative make positive
- subs r2, r1, #1 @ compare divisor with 1
- cmpne r0, r1 @ compare dividend with divisor
- moveq r0, #0
- tsthi r1, r2 @ see if divisor is power of 2
- andeq r0, r0, r2
- bls 10f
-
- ARM_MOD_BODY r0, r1, r2, r3
-
-10: cmp ip, #0
- rsbmi r0, r0, #0
- RET
-
-#endif /* ARM version */
-
- DIV_FUNC_END modsi3
-
-#endif /* L_modsi3 */
-/* ------------------------------------------------------------------------ */
-#ifdef L_dvmd_tls
-
- FUNC_START div0
- FUNC_ALIAS aeabi_idiv0 div0
- FUNC_ALIAS aeabi_ldiv0 div0
-
- RET
-
- FUNC_END aeabi_ldiv0
- FUNC_END aeabi_idiv0
- FUNC_END div0
-
-#endif /* L_divmodsi_tools */
-/* ------------------------------------------------------------------------ */
-#ifdef L_dvmd_lnx
-@ GNU/Linux division-by zero handler. Used in place of L_dvmd_tls
-
-/* Constant taken from <asm/signal.h>. */
-#define SIGFPE 8
-
- .code 32
- FUNC_START div0
-
- stmfd sp!, {r1, lr}
- mov r0, #SIGFPE
- bl SYM(raise) __PLT__
- RETLDM r1
-
- FUNC_END div0
-
-#endif /* L_dvmd_lnx */
-
-/* ------------------------------------------------------------------------ */
-/* Dword multiplication operation. */
-
-#ifdef L_muldi3
-
-# if defined(__ARM_ARCH_6M__)
- FUNC_START muldi3
- FUNC_ALIAS aeabi_lmul muldi3
-# else
- ARM_FUNC_START muldi3
- ARM_FUNC_ALIAS aeabi_lmul muldi3
-# endif
-
- mul yyh, xxl, yyh
- mul ip, yyl, xxh
- umull xxl, xxh, yyl, xxl
- add ip, ip, yyh
- add xxh, xxh, ip
- RET
-
- FUNC_END muldi3
-#endif
-
-/* ------------------------------------------------------------------------ */
-/* Dword shift operations. */
-/* All the following Dword shift variants rely on the fact that
- shft xxx, Reg
- is in fact done as
- shft xxx, (Reg & 255)
- so for Reg value in (32...63) and (-1...-31) we will get zero (in the
- case of logical shifts) or the sign (for asr). */
-
-#ifdef __ARMEB__
-#define al r1
-#define ah r0
-#else
-#define al r0
-#define ah r1
-#endif
-
-/* Prevent __aeabi double-word shifts from being produced on SymbianOS. */
-#ifndef __symbian__
-
-#ifdef L_lshrdi3
-
- FUNC_START lshrdi3
- FUNC_ALIAS aeabi_llsr lshrdi3
-
-#ifdef __thumb__
- lsr al, r2
- mov r3, ah
- lsr ah, r2
- mov ip, r3
- sub r2, #32
- lsr r3, r2
- orr al, r3
- neg r2, r2
- mov r3, ip
- lsl r3, r2
- orr al, r3
- RET
-#else
- subs r3, r2, #32
- rsb ip, r2, #32
- movmi al, al, lsr r2
- movpl al, ah, lsr r3
- orrmi al, al, ah, lsl ip
- mov ah, ah, lsr r2
- RET
-#endif
- FUNC_END aeabi_llsr
- FUNC_END lshrdi3
-
-#endif
-
-#ifdef L_ashrdi3
-
- FUNC_START ashrdi3
- FUNC_ALIAS aeabi_lasr ashrdi3
-
-#ifdef __thumb__
- lsr al, r2
- mov r3, ah
- asr ah, r2
- sub r2, #32
- @ If r2 is negative at this point the following step would OR
- @ the sign bit into all of AL. That's not what we want...
- bmi 1f
- mov ip, r3
- asr r3, r2
- orr al, r3
- mov r3, ip
-1:
- neg r2, r2
- lsl r3, r2
- orr al, r3
- RET
-#else
- subs r3, r2, #32
- rsb ip, r2, #32
- movmi al, al, lsr r2
- movpl al, ah, asr r3
- orrmi al, al, ah, lsl ip
- mov ah, ah, asr r2
- RET
-#endif
-
- FUNC_END aeabi_lasr
- FUNC_END ashrdi3
-
-#endif
-
-#ifdef L_ashldi3
-
- FUNC_START ashldi3
- FUNC_ALIAS aeabi_llsl ashldi3
-
-#ifdef __thumb__
- lsl ah, r2
- mov r3, al
- lsl al, r2
- mov ip, r3
- sub r2, #32
- lsl r3, r2
- orr ah, r3
- neg r2, r2
- mov r3, ip
- lsr r3, r2
- orr ah, r3
- RET
-#else
- subs r3, r2, #32
- rsb ip, r2, #32
- movmi ah, ah, lsl r2
- movpl ah, al, lsl r3
- orrmi ah, ah, al, lsr ip
- mov al, al, lsl r2
- RET
-#endif
- FUNC_END aeabi_llsl
- FUNC_END ashldi3
-
-#endif
-
-#endif /* __symbian__ */
-
-/* ------------------------------------------------------------------------ */
-/* These next two sections are here despite the fact that they contain Thumb
- assembler because their presence allows interworked code to be linked even
- when the GCC library is this one. */
-
-/* Do not build the interworking functions when the target architecture does
- not support Thumb instructions. (This can be a multilib option). */
-#if defined __ARM_ARCH_4T__ || defined __ARM_ARCH_5T__\
- || defined __ARM_ARCH_5TE__ || defined __ARM_ARCH_5TEJ__ \
- || __ARM_ARCH__ >= 6
-
-#if defined 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
- .force_thumb
-
-.macro call_via register
- THUMB_FUNC_START _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 */
-
-#if defined 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.
-
- There are three variations of this code. The first,
- _interwork_call_via_rN(), will push the return address onto the
- stack and pop it in _arm_return(). It should only be used if all
- arguments are passed in registers.
-
- The second, _interwork_r7_call_via_rN(), instead stores the return
- address at [r7, #-4]. It is the caller's responsibility to ensure
- that this address is valid and contains no useful data.
-
- The third, _interwork_r11_call_via_rN(), works in the same way but
- uses r11 instead of r7. It is useful if the caller does not really
- need a frame pointer. */
-
- .text
- .align 0
-
- .code 32
- .globl _arm_return
-LSYM(Lstart_arm_return):
- cfi_start LSYM(Lstart_arm_return) LSYM(Lend_arm_return)
- cfi_push 0, 0xe, -0x8, 0x8
- nop @ This nop is for the benefit of debuggers, so that
- @ backtraces will use the correct unwind information.
-_arm_return:
- RETLDM unwind=LSYM(Lstart_arm_return)
- cfi_end LSYM(Lend_arm_return)
-
- .globl _arm_return_r7
-_arm_return_r7:
- ldr lr, [r7, #-4]
- bx lr
-
- .globl _arm_return_r11
-_arm_return_r11:
- ldr lr, [r11, #-4]
- bx lr
-
-.macro interwork_with_frame frame, register, name, return
- .code 16
-
- THUMB_FUNC_START \name
-
- bx pc
- nop
-
- .code 32
- tst \register, #1
- streq lr, [\frame, #-4]
- adreq lr, _arm_return_\frame
- bx \register
-
- SIZE (\name)
-.endm
-
-.macro interwork register
- .code 16
-
- THUMB_FUNC_START _interwork_call_via_\register
-
- bx pc
- nop
-
- .code 32
- .globl LSYM(Lchange_\register)
-LSYM(Lchange_\register):
- tst \register, #1
- streq lr, [sp, #-8]!
- adreq lr, _arm_return
- bx \register
-
- SIZE (_interwork_call_via_\register)
-
- interwork_with_frame r7,\register,_interwork_r7_call_via_\register
- interwork_with_frame r11,\register,_interwork_r11_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
-
- THUMB_FUNC_START _interwork_call_via_lr
-
- bx pc
- nop
-
- .code 32
- .globl .Lchange_lr
-.Lchange_lr:
- tst lr, #1
- stmeqdb r13!, {lr, pc}
- mov ip, lr
- adreq lr, _arm_return
- bx ip
-
- SIZE (_interwork_call_via_lr)
-
-#endif /* L_interwork_call_via_rX */
-#endif /* Arch supports thumb. */
-
-#ifndef __symbian__
-#include "ieee754-df.S"
-#include "ieee754-sf.S"
-#include "bpabi.S"
-#endif /* __symbian__ */
-
-/* ------------------------------------------------------------------------ */
-/* Fast __clz*2 functions using the clz instruction. These are mainly for
- thumb code. For __ARM_ARCH__ < 5, use C implmentations in arm-libgcc2.c
- instead. */
-
-/* The CLZ instruction is only available on some V5 architectures. */
-
-#if __ARM_ARCH__ > 5 \
- || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
- || defined(__ARM_ARCH_5TEJ__)
-
-#ifdef L_clzsi2
-
- ARM_FUNC_START clzsi2
-
- clz r0, r0
- RET
-
- FUNC_END clzsi2
-
-#endif /* L_clzsi2 */
-
-#ifdef L_clzdi2
-
- ARM_FUNC_START clzdi2
-
- cmp ah, #0
- clzeq r3, al
- clzne r0, ah
- addeq r0, r3, #32
- RET
-
- FUNC_END clzdi2
-
-#endif /* L_clzdi2 */
-
-#endif /* __ARM_ARCH__ > 5 */ \
- /* || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) */ \
- /* || defined(__ARM_ARCH_5TEJ__) */
diff --git a/gcc-4.2.1/gcc/config/arm/libgcc-bpabi.ver b/gcc-4.2.1/gcc/config/arm/libgcc-bpabi.ver
deleted file mode 100644
index 4d94976ec..000000000
--- a/gcc-4.2.1/gcc/config/arm/libgcc-bpabi.ver
+++ /dev/null
@@ -1,89 +0,0 @@
-GCC_3.5 {
- # BPABI symbols
- __aeabi_cdcmpeq
- __aeabi_cdcmple
- __aeabi_cdrcmple
- __aeabi_cfcmpeq
- __aeabi_cfcmple
- __aeabi_cfrcmple
- __aeabi_d2f
- __aeabi_d2iz
- __aeabi_d2lz
- __aeabi_d2uiz
- __aeabi_d2ulz
- __aeabi_dadd
- __aeabi_dcmpeq
- __aeabi_dcmpge
- __aeabi_dcmpgt
- __aeabi_dcmple
- __aeabi_dcmplt
- __aeabi_dcmpun
- __aeabi_ddiv
- __aeabi_dmul
- __aeabi_dneg
- __aeabi_drsub
- __aeabi_dsub
- __aeabi_f2d
- __aeabi_f2iz
- __aeabi_f2lz
- __aeabi_f2uiz
- __aeabi_f2ulz
- __aeabi_fadd
- __aeabi_fcmpeq
- __aeabi_fcmpge
- __aeabi_fcmpgt
- __aeabi_fcmple
- __aeabi_fcmplt
- __aeabi_fcmpun
- __aeabi_fdiv
- __aeabi_fmul
- __aeabi_fneg
- __aeabi_frsub
- __aeabi_fsub
- __aeabi_i2d
- __aeabi_i2f
- __aeabi_idiv
- __aeabi_idiv0
- __aeabi_idivmod
- __aeabi_l2d
- __aeabi_l2f
- __aeabi_lasr
- __aeabi_lcmp
- __aeabi_ldiv0
- __aeabi_ldivmod
- __aeabi_llsl
- __aeabi_llsr
- __aeabi_lmul
- __aeabi_ui2d
- __aeabi_ui2f
- __aeabi_uidiv
- __aeabi_uidivmod
- __aeabi_uldivmod
- __aeabi_ulcmp
- __aeabi_ul2d
- __aeabi_ul2f
- __aeabi_uread4
- __aeabi_uread8
- __aeabi_uwrite4
- __aeabi_uwrite8
-
- # Exception-Handling
- # \S 7.5
- _Unwind_Complete
- _Unwind_VRS_Get
- _Unwind_VRS_Set
- _Unwind_VRS_Pop
- # \S 9.2
- __aeabi_unwind_cpp_pr0
- __aeabi_unwind_cpp_pr1
- __aeabi_unwind_cpp_pr2
- # The libstdc++ exception-handling personality routine uses this
- # GNU-specific entry point.
- __gnu_unwind_frame
-}
-%exclude {
- _Unwind_backtrace
-}
-GCC_4.2.0 {
-_Unwind_Backtrace
-}
diff --git a/gcc-4.2.1/gcc/config/arm/libunwind.S b/gcc-4.2.1/gcc/config/arm/libunwind.S
deleted file mode 100644
index 47625e3c1..000000000
--- a/gcc-4.2.1/gcc/config/arm/libunwind.S
+++ /dev/null
@@ -1,127 +0,0 @@
-/* Support functions for the unwinder.
- Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
- Contributed by Paul Brook
-
- 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 into combinations with other programs,
- and to distribute those combinations 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 a combine
- executable.)
-
- 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, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* An executable stack is *not* required for these functions. */
-#if defined(__ELF__) && defined(__linux__)
-.section .note.GNU-stack,"",%progbits
-.previous
-#endif
-
-#ifndef __symbian__
-
-#include "lib1funcs.asm"
-
-.macro UNPREFIX name
- .global SYM (\name)
- EQUIV SYM (\name), SYM (__\name)
-.endm
-
-/* r0 points to a 16-word block. Upload these values to the actual core
- state. */
-ARM_FUNC_START restore_core_regs
- /* We must use sp as the base register when restoring sp. Push the
- last 3 registers onto the top of the current stack to achieve
- this. */
- add r1, r0, #52
- ldmia r1, {r3, r4, r5} /* {sp, lr, pc}. */
-#ifdef __INTERWORKING__
- /* Restore pc into ip. */
- mov r2, r5
- stmfd sp!, {r2, r3, r4}
-#else
- stmfd sp!, {r3, r4, r5}
-#endif
- /* Don't bother restoring ip. */
- ldmia r0, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp}
- /* Pop the three registers we pushed earlier. */
-#ifdef __INTERWORKING__
- ldmfd sp, {ip, sp, lr}
- bx ip
-#else
- ldmfd sp, {sp, lr, pc}
-#endif
- FUNC_END restore_core_regs
- UNPREFIX restore_core_regs
-
-/* Load VFP registers d0-d15 from the address in r0. */
-ARM_FUNC_START gnu_Unwind_Restore_VFP
- /* Use the generic coprocessor form so that gas doesn't complain
- on soft-float targets. */
- ldc p11,cr0,[r0],{0x21} /* fldmiax r0, {d0-d15} */
- RET
-
-/* Store VFR regsters d0-d15 to the address in r0. */
-ARM_FUNC_START gnu_Unwind_Save_VFP
- /* Use the generic coprocessor form so that gas doesn't complain
- on soft-float targets. */
- stc p11,cr0,[r0],{0x21} /* fstmiax r0, {d0-d15} */
- RET
-
-/* Wrappers to save core registers, then call the real routine. */
-
-.macro UNWIND_WRAPPER name nargs
- ARM_FUNC_START \name
- /* Create a phase2_vrs structure. */
- /* Split reg push in two to ensure the correct value for sp. */
- stmfd sp!, {sp, lr, pc}
- stmfd sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip}
-
- /* Demand-save flags, plus an extra word for alignment. */
- mov r3, #0
- stmfd sp!, {r2, r3}
-
- /* Point r1 at the block. Pass r[0..nargs) unchanged. */
- add r\nargs, sp, #4
-#if defined(__thumb__)
- /* Switch back to thumb mode to avoid interworking hassle. */
- adr ip, .L1_\name
- orr ip, ip, #1
- bx ip
- .thumb
-.L1_\name:
- bl SYM (__gnu\name) __PLT__
- ldr r3, [sp, #64]
- add sp, #72
- bx r3
-#else
- bl SYM (__gnu\name) __PLT__
- ldr lr, [sp, #64]
- add sp, sp, #72
- RET
-#endif
- FUNC_END \name
- UNPREFIX \name
-.endm
-
-UNWIND_WRAPPER _Unwind_RaiseException 1
-UNWIND_WRAPPER _Unwind_Resume 1
-UNWIND_WRAPPER _Unwind_Resume_or_Rethrow 1
-UNWIND_WRAPPER _Unwind_ForcedUnwind 3
-UNWIND_WRAPPER _Unwind_Backtrace 2
-
-#endif /* ndef __symbian__ */
diff --git a/gcc-4.2.1/gcc/config/arm/linux-eabi.h b/gcc-4.2.1/gcc/config/arm/linux-eabi.h
deleted file mode 100644
index 6612f742b..000000000
--- a/gcc-4.2.1/gcc/config/arm/linux-eabi.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* Configuration file for ARM GNU/Linux EABI targets.
- Copyright (C) 2004, 2005, 2006
- Free Software Foundation, Inc.
- Contributed by CodeSourcery, LLC
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* On EABI GNU/Linux, we want both the BPABI builtins and the
- GNU/Linux builtins. */
-#undef TARGET_OS_CPP_BUILTINS
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- TARGET_BPABI_CPP_BUILTINS(); \
- LINUX_TARGET_OS_CPP_BUILTINS(); \
- } \
- while (false)
-
-/* We default to a soft-float ABI so that binaries can run on all
- target hardware. */
-#undef TARGET_DEFAULT_FLOAT_ABI
-#define TARGET_DEFAULT_FLOAT_ABI ARM_FLOAT_ABI_SOFT
-
-/* We default to the "aapcs-linux" ABI so that enums are int-sized by
- default. */
-#undef ARM_DEFAULT_ABI
-#define ARM_DEFAULT_ABI ARM_ABI_AAPCS_LINUX
-
-/* Default to armv5t so that thumb shared libraries work.
- The ARM10TDMI core is the default for armv5t, so set
- SUBTARGET_CPU_DEFAULT to achieve this. */
-#undef SUBTARGET_CPU_DEFAULT
-#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm10tdmi
-
-#undef SUBTARGET_EXTRA_LINK_SPEC
-#define SUBTARGET_EXTRA_LINK_SPEC " -m armelf_linux_eabi"
-
-/* Use ld-linux.so.3 so that it will be possible to run "classic"
- GNU/Linux binaries on an EABI system. */
-#undef GLIBC_DYNAMIC_LINKER
-#define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.3"
-
-/* At this point, bpabi.h will have clobbered LINK_SPEC. We want to
- use the GNU/Linux version, not the generic BPABI version. */
-#undef LINK_SPEC
-#define LINK_SPEC LINUX_TARGET_LINK_SPEC
-
-/* Use the default LIBGCC_SPEC, not the version in linux-elf.h, as we
- do not use -lfloat. */
-#undef LIBGCC_SPEC
-
-/* Use the AAPCS type for wchar_t, or the previous Linux default for
- non-AAPCS. */
-#undef WCHAR_TYPE
-#define WCHAR_TYPE (TARGET_AAPCS_BASED ? "unsigned int" : "long int")
-
-/* Clear the instruction cache from `beg' to `end'. This makes an
- inline system call to SYS_cacheflush. It is modified to work with
- both the original and EABI-only syscall interfaces. */
-#undef CLEAR_INSN_CACHE
-#define CLEAR_INSN_CACHE(BEG, END) \
-{ \
- register unsigned long _beg __asm ("a1") = (unsigned long) (BEG); \
- register unsigned long _end __asm ("a2") = (unsigned long) (END); \
- register unsigned long _flg __asm ("a3") = 0; \
- register unsigned long _scno __asm ("r7") = 0xf0002; \
- __asm __volatile ("swi 0x9f0002 @ sys_cacheflush" \
- : "=r" (_beg) \
- : "0" (_beg), "r" (_end), "r" (_flg), "r" (_scno)); \
-}
diff --git a/gcc-4.2.1/gcc/config/arm/linux-elf.h b/gcc-4.2.1/gcc/config/arm/linux-elf.h
deleted file mode 100644
index a746cf541..000000000
--- a/gcc-4.2.1/gcc/config/arm/linux-elf.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/* Definitions for ARM running Linux-based GNU systems using ELF
- Copyright (C) 1993, 1994, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005, 2006
- Free Software Foundation, Inc.
- Contributed by Philip Blundell <philb@gnu.org>
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* elfos.h should have already been included. Now just override
- any conflicting definitions and add any extras. */
-
-/* Run-time Target Specification. */
-#undef TARGET_VERSION
-#define TARGET_VERSION fputs (" (ARM GNU/Linux with ELF)", stderr);
-
-#undef TARGET_DEFAULT_FLOAT_ABI
-#define TARGET_DEFAULT_FLOAT_ABI ARM_FLOAT_ABI_HARD
-
-#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (0)
-
-#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm6
-
-#define SUBTARGET_EXTRA_LINK_SPEC " -m armelf_linux -p"
-
-#undef MULTILIB_DEFAULTS
-#define MULTILIB_DEFAULTS \
- { "marm", "mlittle-endian", "mhard-float", "mno-thumb-interwork" }
-
-/* Now we define the strings used to build the spec file. */
-#undef LIB_SPEC
-#define LIB_SPEC \
- "%{pthread:-lpthread} \
- %{shared:-lc} \
- %{!shared:%{profile:-lc_p}%{!profile:-lc}}"
-
-#define LIBGCC_SPEC "%{msoft-float:-lfloat} %{mfloat-abi=soft*:-lfloat} -lgcc"
-
-#define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.2"
-
-#define LINUX_TARGET_LINK_SPEC "%{h*} %{version:-v} \
- %{b} \
- %{static:-Bstatic} \
- %{shared:-shared} \
- %{symbolic:-Bsymbolic} \
- %{rdynamic:-export-dynamic} \
- %{!dynamic-linker:-dynamic-linker " LINUX_DYNAMIC_LINKER "} \
- -X \
- %{mbig-endian:-EB}" \
- SUBTARGET_EXTRA_LINK_SPEC
-
-#undef LINK_SPEC
-#define LINK_SPEC LINUX_TARGET_LINK_SPEC
-
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- LINUX_TARGET_OS_CPP_BUILTINS(); \
- } \
- while (0)
-
-/* This is how we tell the assembler that two symbols have the same value. */
-#define ASM_OUTPUT_DEF(FILE, NAME1, NAME2) \
- do \
- { \
- assemble_name (FILE, NAME1); \
- fputs (" = ", FILE); \
- assemble_name (FILE, NAME2); \
- fputc ('\n', FILE); \
- } \
- while (0)
-
-/* NWFPE always understands FPA instructions. */
-#undef FPUTYPE_DEFAULT
-#define FPUTYPE_DEFAULT FPUTYPE_FPA_EMU3
-
-/* Call the function profiler with a given profile label. */
-#undef ARM_FUNCTION_PROFILER
-#define ARM_FUNCTION_PROFILER(STREAM, LABELNO) \
-{ \
- fprintf (STREAM, "\tbl\tmcount%s\n", \
- (TARGET_ARM && NEED_PLT_RELOC) ? "(PLT)" : ""); \
-}
-
-/* The GNU/Linux profiler clobbers the link register. Make sure the
- prologue knows to save it. */
-#define PROFILE_HOOK(X) \
- emit_insn (gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, LR_REGNUM)))
-
-/* The GNU/Linux profiler needs a frame pointer. */
-#define SUBTARGET_FRAME_POINTER_REQUIRED current_function_profile
-
-/* Add .note.GNU-stack. */
-#undef NEED_INDICATE_EXEC_STACK
-#define NEED_INDICATE_EXEC_STACK 1
diff --git a/gcc-4.2.1/gcc/config/arm/linux-gas.h b/gcc-4.2.1/gcc/config/arm/linux-gas.h
deleted file mode 100644
index a04e05066..000000000
--- a/gcc-4.2.1/gcc/config/arm/linux-gas.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* Definitions of target machine for GNU compiler.
- ARM Linux-based GNU systems version.
- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2004
- Free Software Foundation, Inc.
- Contributed by Russell King <rmk92@ecs.soton.ac.uk>.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* This is how we tell the assembler that a symbol is weak.
- GAS always supports weak symbols. */
-
-/* Unsigned chars produces much better code than signed. */
-#define DEFAULT_SIGNED_CHAR 0
-
-#undef SUBTARGET_CPP_SPEC
-#define SUBTARGET_CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}"
-
-#undef SIZE_TYPE
-#define SIZE_TYPE "unsigned int"
-
-#undef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "int"
-
-#undef WCHAR_TYPE
-#define WCHAR_TYPE "long int"
-
-#undef WCHAR_TYPE_SIZE
-#define WCHAR_TYPE_SIZE BITS_PER_WORD
-
-/* Clear the instruction cache from `beg' to `end'. This makes an
- inline system call to SYS_cacheflush. */
-#define CLEAR_INSN_CACHE(BEG, END) \
-{ \
- register unsigned long _beg __asm ("a1") = (unsigned long) (BEG); \
- register unsigned long _end __asm ("a2") = (unsigned long) (END); \
- register unsigned long _flg __asm ("a3") = 0; \
- __asm __volatile ("swi 0x9f0002 @ sys_cacheflush" \
- : "=r" (_beg) \
- : "0" (_beg), "r" (_end), "r" (_flg)); \
-}
diff --git a/gcc-4.2.1/gcc/config/arm/mmintrin.h b/gcc-4.2.1/gcc/config/arm/mmintrin.h
deleted file mode 100644
index bed6204c2..000000000
--- a/gcc-4.2.1/gcc/config/arm/mmintrin.h
+++ /dev/null
@@ -1,1257 +0,0 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING. If not, write to the Free
- Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA. */
-
-/* As a special exception, if you include this header file into source
- files compiled by GCC, this header file 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. */
-
-#ifndef _MMINTRIN_H_INCLUDED
-#define _MMINTRIN_H_INCLUDED
-
-/* The data type intended for user use. */
-typedef unsigned long long __m64, __int64;
-
-/* Internal data types for implementing the intrinsics. */
-typedef int __v2si __attribute__ ((vector_size (8)));
-typedef short __v4hi __attribute__ ((vector_size (8)));
-typedef char __v8qi __attribute__ ((vector_size (8)));
-
-/* "Convert" __m64 and __int64 into each other. */
-static __inline __m64
-_mm_cvtsi64_m64 (__int64 __i)
-{
- return __i;
-}
-
-static __inline __int64
-_mm_cvtm64_si64 (__m64 __i)
-{
- return __i;
-}
-
-static __inline int
-_mm_cvtsi64_si32 (__int64 __i)
-{
- return __i;
-}
-
-static __inline __int64
-_mm_cvtsi32_si64 (int __i)
-{
- return __i;
-}
-
-/* Pack the four 16-bit values from M1 into the lower four 8-bit values of
- the result, and the four 16-bit values from M2 into the upper four 8-bit
- values of the result, all with signed saturation. */
-static __inline __m64
-_mm_packs_pi16 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wpackhss ((__v4hi)__m1, (__v4hi)__m2);
-}
-
-/* Pack the two 32-bit values from M1 in to the lower two 16-bit values of
- the result, and the two 32-bit values from M2 into the upper two 16-bit
- values of the result, all with signed saturation. */
-static __inline __m64
-_mm_packs_pi32 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wpackwss ((__v2si)__m1, (__v2si)__m2);
-}
-
-/* Copy the 64-bit value from M1 into the lower 32-bits of the result, and
- the 64-bit value from M2 into the upper 32-bits of the result, all with
- signed saturation for values that do not fit exactly into 32-bits. */
-static __inline __m64
-_mm_packs_pi64 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wpackdss ((long long)__m1, (long long)__m2);
-}
-
-/* Pack the four 16-bit values from M1 into the lower four 8-bit values of
- the result, and the four 16-bit values from M2 into the upper four 8-bit
- values of the result, all with unsigned saturation. */
-static __inline __m64
-_mm_packs_pu16 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wpackhus ((__v4hi)__m1, (__v4hi)__m2);
-}
-
-/* Pack the two 32-bit values from M1 into the lower two 16-bit values of
- the result, and the two 32-bit values from M2 into the upper two 16-bit
- values of the result, all with unsigned saturation. */
-static __inline __m64
-_mm_packs_pu32 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wpackwus ((__v2si)__m1, (__v2si)__m2);
-}
-
-/* Copy the 64-bit value from M1 into the lower 32-bits of the result, and
- the 64-bit value from M2 into the upper 32-bits of the result, all with
- unsigned saturation for values that do not fit exactly into 32-bits. */
-static __inline __m64
-_mm_packs_pu64 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wpackdus ((long long)__m1, (long long)__m2);
-}
-
-/* Interleave the four 8-bit values from the high half of M1 with the four
- 8-bit values from the high half of M2. */
-static __inline __m64
-_mm_unpackhi_pi8 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wunpckihb ((__v8qi)__m1, (__v8qi)__m2);
-}
-
-/* Interleave the two 16-bit values from the high half of M1 with the two
- 16-bit values from the high half of M2. */
-static __inline __m64
-_mm_unpackhi_pi16 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wunpckihh ((__v4hi)__m1, (__v4hi)__m2);
-}
-
-/* Interleave the 32-bit value from the high half of M1 with the 32-bit
- value from the high half of M2. */
-static __inline __m64
-_mm_unpackhi_pi32 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wunpckihw ((__v2si)__m1, (__v2si)__m2);
-}
-
-/* Interleave the four 8-bit values from the low half of M1 with the four
- 8-bit values from the low half of M2. */
-static __inline __m64
-_mm_unpacklo_pi8 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wunpckilb ((__v8qi)__m1, (__v8qi)__m2);
-}
-
-/* Interleave the two 16-bit values from the low half of M1 with the two
- 16-bit values from the low half of M2. */
-static __inline __m64
-_mm_unpacklo_pi16 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wunpckilh ((__v4hi)__m1, (__v4hi)__m2);
-}
-
-/* Interleave the 32-bit value from the low half of M1 with the 32-bit
- value from the low half of M2. */
-static __inline __m64
-_mm_unpacklo_pi32 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wunpckilw ((__v2si)__m1, (__v2si)__m2);
-}
-
-/* Take the four 8-bit values from the low half of M1, sign extend them,
- and return the result as a vector of four 16-bit quantities. */
-static __inline __m64
-_mm_unpackel_pi8 (__m64 __m1)
-{
- return (__m64) __builtin_arm_wunpckelsb ((__v8qi)__m1);
-}
-
-/* Take the two 16-bit values from the low half of M1, sign extend them,
- and return the result as a vector of two 32-bit quantities. */
-static __inline __m64
-_mm_unpackel_pi16 (__m64 __m1)
-{
- return (__m64) __builtin_arm_wunpckelsh ((__v4hi)__m1);
-}
-
-/* Take the 32-bit value from the low half of M1, and return it sign extended
- to 64 bits. */
-static __inline __m64
-_mm_unpackel_pi32 (__m64 __m1)
-{
- return (__m64) __builtin_arm_wunpckelsw ((__v2si)__m1);
-}
-
-/* Take the four 8-bit values from the high half of M1, sign extend them,
- and return the result as a vector of four 16-bit quantities. */
-static __inline __m64
-_mm_unpackeh_pi8 (__m64 __m1)
-{
- return (__m64) __builtin_arm_wunpckehsb ((__v8qi)__m1);
-}
-
-/* Take the two 16-bit values from the high half of M1, sign extend them,
- and return the result as a vector of two 32-bit quantities. */
-static __inline __m64
-_mm_unpackeh_pi16 (__m64 __m1)
-{
- return (__m64) __builtin_arm_wunpckehsh ((__v4hi)__m1);
-}
-
-/* Take the 32-bit value from the high half of M1, and return it sign extended
- to 64 bits. */
-static __inline __m64
-_mm_unpackeh_pi32 (__m64 __m1)
-{
- return (__m64) __builtin_arm_wunpckehsw ((__v2si)__m1);
-}
-
-/* Take the four 8-bit values from the low half of M1, zero extend them,
- and return the result as a vector of four 16-bit quantities. */
-static __inline __m64
-_mm_unpackel_pu8 (__m64 __m1)
-{
- return (__m64) __builtin_arm_wunpckelub ((__v8qi)__m1);
-}
-
-/* Take the two 16-bit values from the low half of M1, zero extend them,
- and return the result as a vector of two 32-bit quantities. */
-static __inline __m64
-_mm_unpackel_pu16 (__m64 __m1)
-{
- return (__m64) __builtin_arm_wunpckeluh ((__v4hi)__m1);
-}
-
-/* Take the 32-bit value from the low half of M1, and return it zero extended
- to 64 bits. */
-static __inline __m64
-_mm_unpackel_pu32 (__m64 __m1)
-{
- return (__m64) __builtin_arm_wunpckeluw ((__v2si)__m1);
-}
-
-/* Take the four 8-bit values from the high half of M1, zero extend them,
- and return the result as a vector of four 16-bit quantities. */
-static __inline __m64
-_mm_unpackeh_pu8 (__m64 __m1)
-{
- return (__m64) __builtin_arm_wunpckehub ((__v8qi)__m1);
-}
-
-/* Take the two 16-bit values from the high half of M1, zero extend them,
- and return the result as a vector of two 32-bit quantities. */
-static __inline __m64
-_mm_unpackeh_pu16 (__m64 __m1)
-{
- return (__m64) __builtin_arm_wunpckehuh ((__v4hi)__m1);
-}
-
-/* Take the 32-bit value from the high half of M1, and return it zero extended
- to 64 bits. */
-static __inline __m64
-_mm_unpackeh_pu32 (__m64 __m1)
-{
- return (__m64) __builtin_arm_wunpckehuw ((__v2si)__m1);
-}
-
-/* Add the 8-bit values in M1 to the 8-bit values in M2. */
-static __inline __m64
-_mm_add_pi8 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_waddb ((__v8qi)__m1, (__v8qi)__m2);
-}
-
-/* Add the 16-bit values in M1 to the 16-bit values in M2. */
-static __inline __m64
-_mm_add_pi16 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_waddh ((__v4hi)__m1, (__v4hi)__m2);
-}
-
-/* Add the 32-bit values in M1 to the 32-bit values in M2. */
-static __inline __m64
-_mm_add_pi32 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_waddw ((__v2si)__m1, (__v2si)__m2);
-}
-
-/* Add the 8-bit values in M1 to the 8-bit values in M2 using signed
- saturated arithmetic. */
-static __inline __m64
-_mm_adds_pi8 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_waddbss ((__v8qi)__m1, (__v8qi)__m2);
-}
-
-/* Add the 16-bit values in M1 to the 16-bit values in M2 using signed
- saturated arithmetic. */
-static __inline __m64
-_mm_adds_pi16 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_waddhss ((__v4hi)__m1, (__v4hi)__m2);
-}
-
-/* Add the 32-bit values in M1 to the 32-bit values in M2 using signed
- saturated arithmetic. */
-static __inline __m64
-_mm_adds_pi32 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_waddwss ((__v2si)__m1, (__v2si)__m2);
-}
-
-/* Add the 8-bit values in M1 to the 8-bit values in M2 using unsigned
- saturated arithmetic. */
-static __inline __m64
-_mm_adds_pu8 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_waddbus ((__v8qi)__m1, (__v8qi)__m2);
-}
-
-/* Add the 16-bit values in M1 to the 16-bit values in M2 using unsigned
- saturated arithmetic. */
-static __inline __m64
-_mm_adds_pu16 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_waddhus ((__v4hi)__m1, (__v4hi)__m2);
-}
-
-/* Add the 32-bit values in M1 to the 32-bit values in M2 using unsigned
- saturated arithmetic. */
-static __inline __m64
-_mm_adds_pu32 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_waddwus ((__v2si)__m1, (__v2si)__m2);
-}
-
-/* Subtract the 8-bit values in M2 from the 8-bit values in M1. */
-static __inline __m64
-_mm_sub_pi8 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wsubb ((__v8qi)__m1, (__v8qi)__m2);
-}
-
-/* Subtract the 16-bit values in M2 from the 16-bit values in M1. */
-static __inline __m64
-_mm_sub_pi16 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wsubh ((__v4hi)__m1, (__v4hi)__m2);
-}
-
-/* Subtract the 32-bit values in M2 from the 32-bit values in M1. */
-static __inline __m64
-_mm_sub_pi32 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wsubw ((__v2si)__m1, (__v2si)__m2);
-}
-
-/* Subtract the 8-bit values in M2 from the 8-bit values in M1 using signed
- saturating arithmetic. */
-static __inline __m64
-_mm_subs_pi8 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wsubbss ((__v8qi)__m1, (__v8qi)__m2);
-}
-
-/* Subtract the 16-bit values in M2 from the 16-bit values in M1 using
- signed saturating arithmetic. */
-static __inline __m64
-_mm_subs_pi16 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wsubhss ((__v4hi)__m1, (__v4hi)__m2);
-}
-
-/* Subtract the 32-bit values in M2 from the 32-bit values in M1 using
- signed saturating arithmetic. */
-static __inline __m64
-_mm_subs_pi32 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wsubwss ((__v2si)__m1, (__v2si)__m2);
-}
-
-/* Subtract the 8-bit values in M2 from the 8-bit values in M1 using
- unsigned saturating arithmetic. */
-static __inline __m64
-_mm_subs_pu8 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wsubbus ((__v8qi)__m1, (__v8qi)__m2);
-}
-
-/* Subtract the 16-bit values in M2 from the 16-bit values in M1 using
- unsigned saturating arithmetic. */
-static __inline __m64
-_mm_subs_pu16 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wsubhus ((__v4hi)__m1, (__v4hi)__m2);
-}
-
-/* Subtract the 32-bit values in M2 from the 32-bit values in M1 using
- unsigned saturating arithmetic. */
-static __inline __m64
-_mm_subs_pu32 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wsubwus ((__v2si)__m1, (__v2si)__m2);
-}
-
-/* Multiply four 16-bit values in M1 by four 16-bit values in M2 producing
- four 32-bit intermediate results, which are then summed by pairs to
- produce two 32-bit results. */
-static __inline __m64
-_mm_madd_pi16 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wmadds ((__v4hi)__m1, (__v4hi)__m2);
-}
-
-/* Multiply four 16-bit values in M1 by four 16-bit values in M2 producing
- four 32-bit intermediate results, which are then summed by pairs to
- produce two 32-bit results. */
-static __inline __m64
-_mm_madd_pu16 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wmaddu ((__v4hi)__m1, (__v4hi)__m2);
-}
-
-/* Multiply four signed 16-bit values in M1 by four signed 16-bit values in
- M2 and produce the high 16 bits of the 32-bit results. */
-static __inline __m64
-_mm_mulhi_pi16 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wmulsm ((__v4hi)__m1, (__v4hi)__m2);
-}
-
-/* Multiply four signed 16-bit values in M1 by four signed 16-bit values in
- M2 and produce the high 16 bits of the 32-bit results. */
-static __inline __m64
-_mm_mulhi_pu16 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wmulum ((__v4hi)__m1, (__v4hi)__m2);
-}
-
-/* Multiply four 16-bit values in M1 by four 16-bit values in M2 and produce
- the low 16 bits of the results. */
-static __inline __m64
-_mm_mullo_pi16 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wmulul ((__v4hi)__m1, (__v4hi)__m2);
-}
-
-/* Shift four 16-bit values in M left by COUNT. */
-static __inline __m64
-_mm_sll_pi16 (__m64 __m, __m64 __count)
-{
- return (__m64) __builtin_arm_wsllh ((__v4hi)__m, __count);
-}
-
-static __inline __m64
-_mm_slli_pi16 (__m64 __m, int __count)
-{
- return (__m64) __builtin_arm_wsllhi ((__v4hi)__m, __count);
-}
-
-/* Shift two 32-bit values in M left by COUNT. */
-static __inline __m64
-_mm_sll_pi32 (__m64 __m, __m64 __count)
-{
- return (__m64) __builtin_arm_wsllw ((__v2si)__m, __count);
-}
-
-static __inline __m64
-_mm_slli_pi32 (__m64 __m, int __count)
-{
- return (__m64) __builtin_arm_wsllwi ((__v2si)__m, __count);
-}
-
-/* Shift the 64-bit value in M left by COUNT. */
-static __inline __m64
-_mm_sll_si64 (__m64 __m, __m64 __count)
-{
- return (__m64) __builtin_arm_wslld (__m, __count);
-}
-
-static __inline __m64
-_mm_slli_si64 (__m64 __m, int __count)
-{
- return (__m64) __builtin_arm_wslldi (__m, __count);
-}
-
-/* Shift four 16-bit values in M right by COUNT; shift in the sign bit. */
-static __inline __m64
-_mm_sra_pi16 (__m64 __m, __m64 __count)
-{
- return (__m64) __builtin_arm_wsrah ((__v4hi)__m, __count);
-}
-
-static __inline __m64
-_mm_srai_pi16 (__m64 __m, int __count)
-{
- return (__m64) __builtin_arm_wsrahi ((__v4hi)__m, __count);
-}
-
-/* Shift two 32-bit values in M right by COUNT; shift in the sign bit. */
-static __inline __m64
-_mm_sra_pi32 (__m64 __m, __m64 __count)
-{
- return (__m64) __builtin_arm_wsraw ((__v2si)__m, __count);
-}
-
-static __inline __m64
-_mm_srai_pi32 (__m64 __m, int __count)
-{
- return (__m64) __builtin_arm_wsrawi ((__v2si)__m, __count);
-}
-
-/* Shift the 64-bit value in M right by COUNT; shift in the sign bit. */
-static __inline __m64
-_mm_sra_si64 (__m64 __m, __m64 __count)
-{
- return (__m64) __builtin_arm_wsrad (__m, __count);
-}
-
-static __inline __m64
-_mm_srai_si64 (__m64 __m, int __count)
-{
- return (__m64) __builtin_arm_wsradi (__m, __count);
-}
-
-/* Shift four 16-bit values in M right by COUNT; shift in zeros. */
-static __inline __m64
-_mm_srl_pi16 (__m64 __m, __m64 __count)
-{
- return (__m64) __builtin_arm_wsrlh ((__v4hi)__m, __count);
-}
-
-static __inline __m64
-_mm_srli_pi16 (__m64 __m, int __count)
-{
- return (__m64) __builtin_arm_wsrlhi ((__v4hi)__m, __count);
-}
-
-/* Shift two 32-bit values in M right by COUNT; shift in zeros. */
-static __inline __m64
-_mm_srl_pi32 (__m64 __m, __m64 __count)
-{
- return (__m64) __builtin_arm_wsrlw ((__v2si)__m, __count);
-}
-
-static __inline __m64
-_mm_srli_pi32 (__m64 __m, int __count)
-{
- return (__m64) __builtin_arm_wsrlwi ((__v2si)__m, __count);
-}
-
-/* Shift the 64-bit value in M left by COUNT; shift in zeros. */
-static __inline __m64
-_mm_srl_si64 (__m64 __m, __m64 __count)
-{
- return (__m64) __builtin_arm_wsrld (__m, __count);
-}
-
-static __inline __m64
-_mm_srli_si64 (__m64 __m, int __count)
-{
- return (__m64) __builtin_arm_wsrldi (__m, __count);
-}
-
-/* Rotate four 16-bit values in M right by COUNT. */
-static __inline __m64
-_mm_ror_pi16 (__m64 __m, __m64 __count)
-{
- return (__m64) __builtin_arm_wrorh ((__v4hi)__m, __count);
-}
-
-static __inline __m64
-_mm_rori_pi16 (__m64 __m, int __count)
-{
- return (__m64) __builtin_arm_wrorhi ((__v4hi)__m, __count);
-}
-
-/* Rotate two 32-bit values in M right by COUNT. */
-static __inline __m64
-_mm_ror_pi32 (__m64 __m, __m64 __count)
-{
- return (__m64) __builtin_arm_wrorw ((__v2si)__m, __count);
-}
-
-static __inline __m64
-_mm_rori_pi32 (__m64 __m, int __count)
-{
- return (__m64) __builtin_arm_wrorwi ((__v2si)__m, __count);
-}
-
-/* Rotate two 64-bit values in M right by COUNT. */
-static __inline __m64
-_mm_ror_si64 (__m64 __m, __m64 __count)
-{
- return (__m64) __builtin_arm_wrord (__m, __count);
-}
-
-static __inline __m64
-_mm_rori_si64 (__m64 __m, int __count)
-{
- return (__m64) __builtin_arm_wrordi (__m, __count);
-}
-
-/* Bit-wise AND the 64-bit values in M1 and M2. */
-static __inline __m64
-_mm_and_si64 (__m64 __m1, __m64 __m2)
-{
- return __builtin_arm_wand (__m1, __m2);
-}
-
-/* Bit-wise complement the 64-bit value in M1 and bit-wise AND it with the
- 64-bit value in M2. */
-static __inline __m64
-_mm_andnot_si64 (__m64 __m1, __m64 __m2)
-{
- return __builtin_arm_wandn (__m1, __m2);
-}
-
-/* Bit-wise inclusive OR the 64-bit values in M1 and M2. */
-static __inline __m64
-_mm_or_si64 (__m64 __m1, __m64 __m2)
-{
- return __builtin_arm_wor (__m1, __m2);
-}
-
-/* Bit-wise exclusive OR the 64-bit values in M1 and M2. */
-static __inline __m64
-_mm_xor_si64 (__m64 __m1, __m64 __m2)
-{
- return __builtin_arm_wxor (__m1, __m2);
-}
-
-/* Compare eight 8-bit values. The result of the comparison is 0xFF if the
- test is true and zero if false. */
-static __inline __m64
-_mm_cmpeq_pi8 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wcmpeqb ((__v8qi)__m1, (__v8qi)__m2);
-}
-
-static __inline __m64
-_mm_cmpgt_pi8 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wcmpgtsb ((__v8qi)__m1, (__v8qi)__m2);
-}
-
-static __inline __m64
-_mm_cmpgt_pu8 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wcmpgtub ((__v8qi)__m1, (__v8qi)__m2);
-}
-
-/* Compare four 16-bit values. The result of the comparison is 0xFFFF if
- the test is true and zero if false. */
-static __inline __m64
-_mm_cmpeq_pi16 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wcmpeqh ((__v4hi)__m1, (__v4hi)__m2);
-}
-
-static __inline __m64
-_mm_cmpgt_pi16 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wcmpgtsh ((__v4hi)__m1, (__v4hi)__m2);
-}
-
-static __inline __m64
-_mm_cmpgt_pu16 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wcmpgtuh ((__v4hi)__m1, (__v4hi)__m2);
-}
-
-/* Compare two 32-bit values. The result of the comparison is 0xFFFFFFFF if
- the test is true and zero if false. */
-static __inline __m64
-_mm_cmpeq_pi32 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wcmpeqw ((__v2si)__m1, (__v2si)__m2);
-}
-
-static __inline __m64
-_mm_cmpgt_pi32 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wcmpgtsw ((__v2si)__m1, (__v2si)__m2);
-}
-
-static __inline __m64
-_mm_cmpgt_pu32 (__m64 __m1, __m64 __m2)
-{
- return (__m64) __builtin_arm_wcmpgtuw ((__v2si)__m1, (__v2si)__m2);
-}
-
-/* Element-wise multiplication of unsigned 16-bit values __B and __C, followed
- by accumulate across all elements and __A. */
-static __inline __m64
-_mm_mac_pu16 (__m64 __A, __m64 __B, __m64 __C)
-{
- return __builtin_arm_wmacu (__A, (__v4hi)__B, (__v4hi)__C);
-}
-
-/* Element-wise multiplication of signed 16-bit values __B and __C, followed
- by accumulate across all elements and __A. */
-static __inline __m64
-_mm_mac_pi16 (__m64 __A, __m64 __B, __m64 __C)
-{
- return __builtin_arm_wmacs (__A, (__v4hi)__B, (__v4hi)__C);
-}
-
-/* Element-wise multiplication of unsigned 16-bit values __B and __C, followed
- by accumulate across all elements. */
-static __inline __m64
-_mm_macz_pu16 (__m64 __A, __m64 __B)
-{
- return __builtin_arm_wmacuz ((__v4hi)__A, (__v4hi)__B);
-}
-
-/* Element-wise multiplication of signed 16-bit values __B and __C, followed
- by accumulate across all elements. */
-static __inline __m64
-_mm_macz_pi16 (__m64 __A, __m64 __B)
-{
- return __builtin_arm_wmacsz ((__v4hi)__A, (__v4hi)__B);
-}
-
-/* Accumulate across all unsigned 8-bit values in __A. */
-static __inline __m64
-_mm_acc_pu8 (__m64 __A)
-{
- return __builtin_arm_waccb ((__v8qi)__A);
-}
-
-/* Accumulate across all unsigned 16-bit values in __A. */
-static __inline __m64
-_mm_acc_pu16 (__m64 __A)
-{
- return __builtin_arm_wacch ((__v4hi)__A);
-}
-
-/* Accumulate across all unsigned 32-bit values in __A. */
-static __inline __m64
-_mm_acc_pu32 (__m64 __A)
-{
- return __builtin_arm_waccw ((__v2si)__A);
-}
-
-static __inline __m64
-_mm_mia_si64 (__m64 __A, int __B, int __C)
-{
- return __builtin_arm_tmia (__A, __B, __C);
-}
-
-static __inline __m64
-_mm_miaph_si64 (__m64 __A, int __B, int __C)
-{
- return __builtin_arm_tmiaph (__A, __B, __C);
-}
-
-static __inline __m64
-_mm_miabb_si64 (__m64 __A, int __B, int __C)
-{
- return __builtin_arm_tmiabb (__A, __B, __C);
-}
-
-static __inline __m64
-_mm_miabt_si64 (__m64 __A, int __B, int __C)
-{
- return __builtin_arm_tmiabt (__A, __B, __C);
-}
-
-static __inline __m64
-_mm_miatb_si64 (__m64 __A, int __B, int __C)
-{
- return __builtin_arm_tmiatb (__A, __B, __C);
-}
-
-static __inline __m64
-_mm_miatt_si64 (__m64 __A, int __B, int __C)
-{
- return __builtin_arm_tmiatt (__A, __B, __C);
-}
-
-/* Extract one of the elements of A and sign extend. The selector N must
- be immediate. */
-#define _mm_extract_pi8(A, N) __builtin_arm_textrmsb ((__v8qi)(A), (N))
-#define _mm_extract_pi16(A, N) __builtin_arm_textrmsh ((__v4hi)(A), (N))
-#define _mm_extract_pi32(A, N) __builtin_arm_textrmsw ((__v2si)(A), (N))
-
-/* Extract one of the elements of A and zero extend. The selector N must
- be immediate. */
-#define _mm_extract_pu8(A, N) __builtin_arm_textrmub ((__v8qi)(A), (N))
-#define _mm_extract_pu16(A, N) __builtin_arm_textrmuh ((__v4hi)(A), (N))
-#define _mm_extract_pu32(A, N) __builtin_arm_textrmuw ((__v2si)(A), (N))
-
-/* Inserts word D into one of the elements of A. The selector N must be
- immediate. */
-#define _mm_insert_pi8(A, D, N) \
- ((__m64) __builtin_arm_tinsrb ((__v8qi)(A), (D), (N)))
-#define _mm_insert_pi16(A, D, N) \
- ((__m64) __builtin_arm_tinsrh ((__v4hi)(A), (D), (N)))
-#define _mm_insert_pi32(A, D, N) \
- ((__m64) __builtin_arm_tinsrw ((__v2si)(A), (D), (N)))
-
-/* Compute the element-wise maximum of signed 8-bit values. */
-static __inline __m64
-_mm_max_pi8 (__m64 __A, __m64 __B)
-{
- return (__m64) __builtin_arm_wmaxsb ((__v8qi)__A, (__v8qi)__B);
-}
-
-/* Compute the element-wise maximum of signed 16-bit values. */
-static __inline __m64
-_mm_max_pi16 (__m64 __A, __m64 __B)
-{
- return (__m64) __builtin_arm_wmaxsh ((__v4hi)__A, (__v4hi)__B);
-}
-
-/* Compute the element-wise maximum of signed 32-bit values. */
-static __inline __m64
-_mm_max_pi32 (__m64 __A, __m64 __B)
-{
- return (__m64) __builtin_arm_wmaxsw ((__v2si)__A, (__v2si)__B);
-}
-
-/* Compute the element-wise maximum of unsigned 8-bit values. */
-static __inline __m64
-_mm_max_pu8 (__m64 __A, __m64 __B)
-{
- return (__m64) __builtin_arm_wmaxub ((__v8qi)__A, (__v8qi)__B);
-}
-
-/* Compute the element-wise maximum of unsigned 16-bit values. */
-static __inline __m64
-_mm_max_pu16 (__m64 __A, __m64 __B)
-{
- return (__m64) __builtin_arm_wmaxuh ((__v4hi)__A, (__v4hi)__B);
-}
-
-/* Compute the element-wise maximum of unsigned 32-bit values. */
-static __inline __m64
-_mm_max_pu32 (__m64 __A, __m64 __B)
-{
- return (__m64) __builtin_arm_wmaxuw ((__v2si)__A, (__v2si)__B);
-}
-
-/* Compute the element-wise minimum of signed 16-bit values. */
-static __inline __m64
-_mm_min_pi8 (__m64 __A, __m64 __B)
-{
- return (__m64) __builtin_arm_wminsb ((__v8qi)__A, (__v8qi)__B);
-}
-
-/* Compute the element-wise minimum of signed 16-bit values. */
-static __inline __m64
-_mm_min_pi16 (__m64 __A, __m64 __B)
-{
- return (__m64) __builtin_arm_wminsh ((__v4hi)__A, (__v4hi)__B);
-}
-
-/* Compute the element-wise minimum of signed 32-bit values. */
-static __inline __m64
-_mm_min_pi32 (__m64 __A, __m64 __B)
-{
- return (__m64) __builtin_arm_wminsw ((__v2si)__A, (__v2si)__B);
-}
-
-/* Compute the element-wise minimum of unsigned 16-bit values. */
-static __inline __m64
-_mm_min_pu8 (__m64 __A, __m64 __B)
-{
- return (__m64) __builtin_arm_wminub ((__v8qi)__A, (__v8qi)__B);
-}
-
-/* Compute the element-wise minimum of unsigned 16-bit values. */
-static __inline __m64
-_mm_min_pu16 (__m64 __A, __m64 __B)
-{
- return (__m64) __builtin_arm_wminuh ((__v4hi)__A, (__v4hi)__B);
-}
-
-/* Compute the element-wise minimum of unsigned 32-bit values. */
-static __inline __m64
-_mm_min_pu32 (__m64 __A, __m64 __B)
-{
- return (__m64) __builtin_arm_wminuw ((__v2si)__A, (__v2si)__B);
-}
-
-/* Create an 8-bit mask of the signs of 8-bit values. */
-static __inline int
-_mm_movemask_pi8 (__m64 __A)
-{
- return __builtin_arm_tmovmskb ((__v8qi)__A);
-}
-
-/* Create an 8-bit mask of the signs of 16-bit values. */
-static __inline int
-_mm_movemask_pi16 (__m64 __A)
-{
- return __builtin_arm_tmovmskh ((__v4hi)__A);
-}
-
-/* Create an 8-bit mask of the signs of 32-bit values. */
-static __inline int
-_mm_movemask_pi32 (__m64 __A)
-{
- return __builtin_arm_tmovmskw ((__v2si)__A);
-}
-
-/* Return a combination of the four 16-bit values in A. The selector
- must be an immediate. */
-#define _mm_shuffle_pi16(A, N) \
- ((__m64) __builtin_arm_wshufh ((__v4hi)(A), (N)))
-
-
-/* Compute the rounded averages of the unsigned 8-bit values in A and B. */
-static __inline __m64
-_mm_avg_pu8 (__m64 __A, __m64 __B)
-{
- return (__m64) __builtin_arm_wavg2br ((__v8qi)__A, (__v8qi)__B);
-}
-
-/* Compute the rounded averages of the unsigned 16-bit values in A and B. */
-static __inline __m64
-_mm_avg_pu16 (__m64 __A, __m64 __B)
-{
- return (__m64) __builtin_arm_wavg2hr ((__v4hi)__A, (__v4hi)__B);
-}
-
-/* Compute the averages of the unsigned 8-bit values in A and B. */
-static __inline __m64
-_mm_avg2_pu8 (__m64 __A, __m64 __B)
-{
- return (__m64) __builtin_arm_wavg2b ((__v8qi)__A, (__v8qi)__B);
-}
-
-/* Compute the averages of the unsigned 16-bit values in A and B. */
-static __inline __m64
-_mm_avg2_pu16 (__m64 __A, __m64 __B)
-{
- return (__m64) __builtin_arm_wavg2h ((__v4hi)__A, (__v4hi)__B);
-}
-
-/* Compute the sum of the absolute differences of the unsigned 8-bit
- values in A and B. Return the value in the lower 16-bit word; the
- upper words are cleared. */
-static __inline __m64
-_mm_sad_pu8 (__m64 __A, __m64 __B)
-{
- return (__m64) __builtin_arm_wsadb ((__v8qi)__A, (__v8qi)__B);
-}
-
-/* Compute the sum of the absolute differences of the unsigned 16-bit
- values in A and B. Return the value in the lower 32-bit word; the
- upper words are cleared. */
-static __inline __m64
-_mm_sad_pu16 (__m64 __A, __m64 __B)
-{
- return (__m64) __builtin_arm_wsadh ((__v4hi)__A, (__v4hi)__B);
-}
-
-/* Compute the sum of the absolute differences of the unsigned 8-bit
- values in A and B. Return the value in the lower 16-bit word; the
- upper words are cleared. */
-static __inline __m64
-_mm_sadz_pu8 (__m64 __A, __m64 __B)
-{
- return (__m64) __builtin_arm_wsadbz ((__v8qi)__A, (__v8qi)__B);
-}
-
-/* Compute the sum of the absolute differences of the unsigned 16-bit
- values in A and B. Return the value in the lower 32-bit word; the
- upper words are cleared. */
-static __inline __m64
-_mm_sadz_pu16 (__m64 __A, __m64 __B)
-{
- return (__m64) __builtin_arm_wsadhz ((__v4hi)__A, (__v4hi)__B);
-}
-
-static __inline __m64
-_mm_align_si64 (__m64 __A, __m64 __B, int __C)
-{
- return (__m64) __builtin_arm_walign ((__v8qi)__A, (__v8qi)__B, __C);
-}
-
-/* Creates a 64-bit zero. */
-static __inline __m64
-_mm_setzero_si64 (void)
-{
- return __builtin_arm_wzero ();
-}
-
-/* Set and Get arbitrary iWMMXt Control registers.
- Note only registers 0-3 and 8-11 are currently defined,
- the rest are reserved. */
-
-static __inline void
-_mm_setwcx (const int __value, const int __regno)
-{
- switch (__regno)
- {
- case 0: __builtin_arm_setwcx (__value, 0); break;
- case 1: __builtin_arm_setwcx (__value, 1); break;
- case 2: __builtin_arm_setwcx (__value, 2); break;
- case 3: __builtin_arm_setwcx (__value, 3); break;
- case 8: __builtin_arm_setwcx (__value, 8); break;
- case 9: __builtin_arm_setwcx (__value, 9); break;
- case 10: __builtin_arm_setwcx (__value, 10); break;
- case 11: __builtin_arm_setwcx (__value, 11); break;
- default: break;
- }
-}
-
-static __inline int
-_mm_getwcx (const int __regno)
-{
- switch (__regno)
- {
- case 0: return __builtin_arm_getwcx (0);
- case 1: return __builtin_arm_getwcx (1);
- case 2: return __builtin_arm_getwcx (2);
- case 3: return __builtin_arm_getwcx (3);
- case 8: return __builtin_arm_getwcx (8);
- case 9: return __builtin_arm_getwcx (9);
- case 10: return __builtin_arm_getwcx (10);
- case 11: return __builtin_arm_getwcx (11);
- default: return 0;
- }
-}
-
-/* Creates a vector of two 32-bit values; I0 is least significant. */
-static __inline __m64
-_mm_set_pi32 (int __i1, int __i0)
-{
- union {
- __m64 __q;
- struct {
- unsigned int __i0;
- unsigned int __i1;
- } __s;
- } __u;
-
- __u.__s.__i0 = __i0;
- __u.__s.__i1 = __i1;
-
- return __u.__q;
-}
-
-/* Creates a vector of four 16-bit values; W0 is least significant. */
-static __inline __m64
-_mm_set_pi16 (short __w3, short __w2, short __w1, short __w0)
-{
- unsigned int __i1 = (unsigned short)__w3 << 16 | (unsigned short)__w2;
- unsigned int __i0 = (unsigned short)__w1 << 16 | (unsigned short)__w0;
- return _mm_set_pi32 (__i1, __i0);
-
-}
-
-/* Creates a vector of eight 8-bit values; B0 is least significant. */
-static __inline __m64
-_mm_set_pi8 (char __b7, char __b6, char __b5, char __b4,
- char __b3, char __b2, char __b1, char __b0)
-{
- unsigned int __i1, __i0;
-
- __i1 = (unsigned char)__b7;
- __i1 = __i1 << 8 | (unsigned char)__b6;
- __i1 = __i1 << 8 | (unsigned char)__b5;
- __i1 = __i1 << 8 | (unsigned char)__b4;
-
- __i0 = (unsigned char)__b3;
- __i0 = __i0 << 8 | (unsigned char)__b2;
- __i0 = __i0 << 8 | (unsigned char)__b1;
- __i0 = __i0 << 8 | (unsigned char)__b0;
-
- return _mm_set_pi32 (__i1, __i0);
-}
-
-/* Similar, but with the arguments in reverse order. */
-static __inline __m64
-_mm_setr_pi32 (int __i0, int __i1)
-{
- return _mm_set_pi32 (__i1, __i0);
-}
-
-static __inline __m64
-_mm_setr_pi16 (short __w0, short __w1, short __w2, short __w3)
-{
- return _mm_set_pi16 (__w3, __w2, __w1, __w0);
-}
-
-static __inline __m64
-_mm_setr_pi8 (char __b0, char __b1, char __b2, char __b3,
- char __b4, char __b5, char __b6, char __b7)
-{
- return _mm_set_pi8 (__b7, __b6, __b5, __b4, __b3, __b2, __b1, __b0);
-}
-
-/* Creates a vector of two 32-bit values, both elements containing I. */
-static __inline __m64
-_mm_set1_pi32 (int __i)
-{
- return _mm_set_pi32 (__i, __i);
-}
-
-/* Creates a vector of four 16-bit values, all elements containing W. */
-static __inline __m64
-_mm_set1_pi16 (short __w)
-{
- unsigned int __i = (unsigned short)__w << 16 | (unsigned short)__w;
- return _mm_set1_pi32 (__i);
-}
-
-/* Creates a vector of four 16-bit values, all elements containing B. */
-static __inline __m64
-_mm_set1_pi8 (char __b)
-{
- unsigned int __w = (unsigned char)__b << 8 | (unsigned char)__b;
- unsigned int __i = __w << 16 | __w;
- return _mm_set1_pi32 (__i);
-}
-
-/* Convert an integer to a __m64 object. */
-static __inline __m64
-_m_from_int (int __a)
-{
- return (__m64)__a;
-}
-
-#define _m_packsswb _mm_packs_pi16
-#define _m_packssdw _mm_packs_pi32
-#define _m_packuswb _mm_packs_pu16
-#define _m_packusdw _mm_packs_pu32
-#define _m_packssqd _mm_packs_pi64
-#define _m_packusqd _mm_packs_pu64
-#define _mm_packs_si64 _mm_packs_pi64
-#define _mm_packs_su64 _mm_packs_pu64
-#define _m_punpckhbw _mm_unpackhi_pi8
-#define _m_punpckhwd _mm_unpackhi_pi16
-#define _m_punpckhdq _mm_unpackhi_pi32
-#define _m_punpcklbw _mm_unpacklo_pi8
-#define _m_punpcklwd _mm_unpacklo_pi16
-#define _m_punpckldq _mm_unpacklo_pi32
-#define _m_punpckehsbw _mm_unpackeh_pi8
-#define _m_punpckehswd _mm_unpackeh_pi16
-#define _m_punpckehsdq _mm_unpackeh_pi32
-#define _m_punpckehubw _mm_unpackeh_pu8
-#define _m_punpckehuwd _mm_unpackeh_pu16
-#define _m_punpckehudq _mm_unpackeh_pu32
-#define _m_punpckelsbw _mm_unpackel_pi8
-#define _m_punpckelswd _mm_unpackel_pi16
-#define _m_punpckelsdq _mm_unpackel_pi32
-#define _m_punpckelubw _mm_unpackel_pu8
-#define _m_punpckeluwd _mm_unpackel_pu16
-#define _m_punpckeludq _mm_unpackel_pu32
-#define _m_paddb _mm_add_pi8
-#define _m_paddw _mm_add_pi16
-#define _m_paddd _mm_add_pi32
-#define _m_paddsb _mm_adds_pi8
-#define _m_paddsw _mm_adds_pi16
-#define _m_paddsd _mm_adds_pi32
-#define _m_paddusb _mm_adds_pu8
-#define _m_paddusw _mm_adds_pu16
-#define _m_paddusd _mm_adds_pu32
-#define _m_psubb _mm_sub_pi8
-#define _m_psubw _mm_sub_pi16
-#define _m_psubd _mm_sub_pi32
-#define _m_psubsb _mm_subs_pi8
-#define _m_psubsw _mm_subs_pi16
-#define _m_psubuw _mm_subs_pi32
-#define _m_psubusb _mm_subs_pu8
-#define _m_psubusw _mm_subs_pu16
-#define _m_psubusd _mm_subs_pu32
-#define _m_pmaddwd _mm_madd_pi16
-#define _m_pmadduwd _mm_madd_pu16
-#define _m_pmulhw _mm_mulhi_pi16
-#define _m_pmulhuw _mm_mulhi_pu16
-#define _m_pmullw _mm_mullo_pi16
-#define _m_pmacsw _mm_mac_pi16
-#define _m_pmacuw _mm_mac_pu16
-#define _m_pmacszw _mm_macz_pi16
-#define _m_pmacuzw _mm_macz_pu16
-#define _m_paccb _mm_acc_pu8
-#define _m_paccw _mm_acc_pu16
-#define _m_paccd _mm_acc_pu32
-#define _m_pmia _mm_mia_si64
-#define _m_pmiaph _mm_miaph_si64
-#define _m_pmiabb _mm_miabb_si64
-#define _m_pmiabt _mm_miabt_si64
-#define _m_pmiatb _mm_miatb_si64
-#define _m_pmiatt _mm_miatt_si64
-#define _m_psllw _mm_sll_pi16
-#define _m_psllwi _mm_slli_pi16
-#define _m_pslld _mm_sll_pi32
-#define _m_pslldi _mm_slli_pi32
-#define _m_psllq _mm_sll_si64
-#define _m_psllqi _mm_slli_si64
-#define _m_psraw _mm_sra_pi16
-#define _m_psrawi _mm_srai_pi16
-#define _m_psrad _mm_sra_pi32
-#define _m_psradi _mm_srai_pi32
-#define _m_psraq _mm_sra_si64
-#define _m_psraqi _mm_srai_si64
-#define _m_psrlw _mm_srl_pi16
-#define _m_psrlwi _mm_srli_pi16
-#define _m_psrld _mm_srl_pi32
-#define _m_psrldi _mm_srli_pi32
-#define _m_psrlq _mm_srl_si64
-#define _m_psrlqi _mm_srli_si64
-#define _m_prorw _mm_ror_pi16
-#define _m_prorwi _mm_rori_pi16
-#define _m_prord _mm_ror_pi32
-#define _m_prordi _mm_rori_pi32
-#define _m_prorq _mm_ror_si64
-#define _m_prorqi _mm_rori_si64
-#define _m_pand _mm_and_si64
-#define _m_pandn _mm_andnot_si64
-#define _m_por _mm_or_si64
-#define _m_pxor _mm_xor_si64
-#define _m_pcmpeqb _mm_cmpeq_pi8
-#define _m_pcmpeqw _mm_cmpeq_pi16
-#define _m_pcmpeqd _mm_cmpeq_pi32
-#define _m_pcmpgtb _mm_cmpgt_pi8
-#define _m_pcmpgtub _mm_cmpgt_pu8
-#define _m_pcmpgtw _mm_cmpgt_pi16
-#define _m_pcmpgtuw _mm_cmpgt_pu16
-#define _m_pcmpgtd _mm_cmpgt_pi32
-#define _m_pcmpgtud _mm_cmpgt_pu32
-#define _m_pextrb _mm_extract_pi8
-#define _m_pextrw _mm_extract_pi16
-#define _m_pextrd _mm_extract_pi32
-#define _m_pextrub _mm_extract_pu8
-#define _m_pextruw _mm_extract_pu16
-#define _m_pextrud _mm_extract_pu32
-#define _m_pinsrb _mm_insert_pi8
-#define _m_pinsrw _mm_insert_pi16
-#define _m_pinsrd _mm_insert_pi32
-#define _m_pmaxsb _mm_max_pi8
-#define _m_pmaxsw _mm_max_pi16
-#define _m_pmaxsd _mm_max_pi32
-#define _m_pmaxub _mm_max_pu8
-#define _m_pmaxuw _mm_max_pu16
-#define _m_pmaxud _mm_max_pu32
-#define _m_pminsb _mm_min_pi8
-#define _m_pminsw _mm_min_pi16
-#define _m_pminsd _mm_min_pi32
-#define _m_pminub _mm_min_pu8
-#define _m_pminuw _mm_min_pu16
-#define _m_pminud _mm_min_pu32
-#define _m_pmovmskb _mm_movemask_pi8
-#define _m_pmovmskw _mm_movemask_pi16
-#define _m_pmovmskd _mm_movemask_pi32
-#define _m_pshufw _mm_shuffle_pi16
-#define _m_pavgb _mm_avg_pu8
-#define _m_pavgw _mm_avg_pu16
-#define _m_pavg2b _mm_avg2_pu8
-#define _m_pavg2w _mm_avg2_pu16
-#define _m_psadbw _mm_sad_pu8
-#define _m_psadwd _mm_sad_pu16
-#define _m_psadzbw _mm_sadz_pu8
-#define _m_psadzwd _mm_sadz_pu16
-#define _m_paligniq _mm_align_si64
-#define _m_cvt_si2pi _mm_cvtsi64_m64
-#define _m_cvt_pi2si _mm_cvtm64_si64
-
-#endif /* _MMINTRIN_H_INCLUDED */
diff --git a/gcc-4.2.1/gcc/config/arm/netbsd-elf.h b/gcc-4.2.1/gcc/config/arm/netbsd-elf.h
deleted file mode 100644
index 8a01b0fcc..000000000
--- a/gcc-4.2.1/gcc/config/arm/netbsd-elf.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/* Definitions of target machine for GNU compiler, NetBSD/arm ELF version.
- Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
- Contributed by Wasabi Systems, Inc.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* Run-time Target Specification. */
-#undef TARGET_VERSION
-#define TARGET_VERSION fputs (" (NetBSD/arm ELF)", stderr);
-
-/* arm.h defaults to ARM6 CPU. */
-
-/* This defaults us to little-endian. */
-#ifndef TARGET_ENDIAN_DEFAULT
-#define TARGET_ENDIAN_DEFAULT 0
-#endif
-
-#undef MULTILIB_DEFAULTS
-
-/* Default it to use ATPCS with soft-VFP. */
-#undef TARGET_DEFAULT
-#define TARGET_DEFAULT \
- (MASK_APCS_FRAME \
- | TARGET_ENDIAN_DEFAULT)
-
-#undef ARM_DEFAULT_ABI
-#define ARM_DEFAULT_ABI ARM_ABI_ATPCS
-
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- NETBSD_OS_CPP_BUILTINS_ELF(); \
- } \
- while (0)
-
-#undef SUBTARGET_CPP_SPEC
-#define SUBTARGET_CPP_SPEC NETBSD_CPP_SPEC
-
-#undef SUBTARGET_EXTRA_ASM_SPEC
-#define SUBTARGET_EXTRA_ASM_SPEC \
- "-matpcs %{fpic|fpie:-k} %{fPIC|fPIE:-k}"
-
-/* Default to full VFP if -mhard-float is specified. */
-#undef SUBTARGET_ASM_FLOAT_SPEC
-#define SUBTARGET_ASM_FLOAT_SPEC \
- "%{mhard-float:{!mfpu=*:-mfpu=vfp}} \
- %{mfloat-abi=hard:{!mfpu=*:-mfpu=vfp}}"
-
-#undef SUBTARGET_EXTRA_SPECS
-#define SUBTARGET_EXTRA_SPECS \
- { "subtarget_extra_asm_spec", SUBTARGET_EXTRA_ASM_SPEC }, \
- { "subtarget_asm_float_spec", SUBTARGET_ASM_FLOAT_SPEC }, \
- { "netbsd_link_spec", NETBSD_LINK_SPEC_ELF }, \
- { "netbsd_entry_point", NETBSD_ENTRY_POINT },
-
-#define NETBSD_ENTRY_POINT "__start"
-
-#undef LINK_SPEC
-#define LINK_SPEC \
- "-X %{mbig-endian:-EB} %{mlittle-endian:-EL} \
- %(netbsd_link_spec)"
-
-/* Make GCC agree with <machine/ansi.h>. */
-
-#undef SIZE_TYPE
-#define SIZE_TYPE "long unsigned int"
-
-#undef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "long int"
-
-/* We don't have any limit on the length as out debugger is GDB. */
-#undef DBX_CONTIN_LENGTH
-
-/* NetBSD does its profiling differently to the Acorn compiler. We
- don't need a word following the mcount call; and to skip it
- requires either an assembly stub or use of fomit-frame-pointer when
- compiling the profiling functions. Since we break Acorn CC
- compatibility below a little more won't hurt. */
-
-#undef ARM_FUNCTION_PROFILER
-#define ARM_FUNCTION_PROFILER(STREAM,LABELNO) \
-{ \
- asm_fprintf (STREAM, "\tmov\t%Rip, %Rlr\n"); \
- asm_fprintf (STREAM, "\tbl\t__mcount%s\n", \
- (TARGET_ARM && NEED_PLT_RELOC) \
- ? "(PLT)" : ""); \
-}
-
-/* VERY BIG NOTE: Change of structure alignment for NetBSD/arm.
- There are consequences you should be aware of...
-
- Normally GCC/arm uses a structure alignment of 32 for compatibility
- with armcc. This means that structures are padded to a word
- boundary. However this causes problems with bugged NetBSD kernel
- code (possibly userland code as well - I have not checked every
- binary). The nature of this bugged code is to rely on sizeof()
- returning the correct size of various structures rounded to the
- nearest byte (SCSI and ether code are two examples, the vm system
- is another). This code breaks when the structure alignment is 32
- as sizeof() will report a word=rounded size. By changing the
- structure alignment to 8. GCC will conform to what is expected by
- NetBSD.
-
- This has several side effects that should be considered.
- 1. Structures will only be aligned to the size of the largest member.
- i.e. structures containing only bytes will be byte aligned.
- structures containing shorts will be half word aligned.
- structures containing ints will be word aligned.
-
- This means structures should be padded to a word boundary if
- alignment of 32 is required for byte structures etc.
-
- 2. A potential performance penalty may exist if strings are no longer
- word aligned. GCC will not be able to use word load/stores to copy
- short strings.
-
- This modification is not encouraged but with the present state of the
- NetBSD source tree it is currently the only solution that meets the
- requirements. */
-
-#undef DEFAULT_STRUCTURE_SIZE_BOUNDARY
-#define DEFAULT_STRUCTURE_SIZE_BOUNDARY 8
-
-/* Clear the instruction cache from `BEG' to `END'. This makes a
- call to the ARM_SYNC_ICACHE architecture specific syscall. */
-#define CLEAR_INSN_CACHE(BEG, END) \
-do \
- { \
- extern int sysarch(int number, void *args); \
- struct \
- { \
- unsigned int addr; \
- int len; \
- } s; \
- s.addr = (unsigned int)(BEG); \
- s.len = (END) - (BEG); \
- (void) sysarch (0, &s); \
- } \
-while (0)
-
-#undef FPUTYPE_DEFAULT
-#define FPUTYPE_DEFAULT FPUTYPE_VFP
-
diff --git a/gcc-4.2.1/gcc/config/arm/netbsd.h b/gcc-4.2.1/gcc/config/arm/netbsd.h
deleted file mode 100644
index 4d147442c..000000000
--- a/gcc-4.2.1/gcc/config/arm/netbsd.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/* NetBSD/arm a.out version.
- Copyright (C) 1993, 1994, 1997, 1998, 2003, 2004, 2005
- Free Software Foundation, Inc.
- Contributed by Mark Brinicombe (amb@physig.ph.kcl.ac.uk)
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* Run-time Target Specification. */
-#undef TARGET_VERSION
-#define TARGET_VERSION fputs (" (ARM/NetBSD)", stderr);
-
-/* Unsigned chars produces much better code than signed. */
-#define DEFAULT_SIGNED_CHAR 0
-
-/* Since we always use GAS as our assembler we support stabs. */
-#define DBX_DEBUGGING_INFO 1
-
-/*#undef ASM_DECLARE_FUNCTION_NAME*/
-
-/* ARM6 family default cpu. */
-#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm6
-
-#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_APCS_FRAME)
-
-/* Some defines for CPP.
- arm32 is the NetBSD port name, so we always define arm32 and __arm32__. */
-#define TARGET_OS_CPP_BUILTINS() \
- do { \
- NETBSD_OS_CPP_BUILTINS_AOUT(); \
- builtin_define_std ("arm32"); \
- builtin_define_std ("unix"); \
- builtin_define_std ("riscbsd"); \
- } while (0)
-
-#undef SUBTARGET_EXTRA_SPECS
-#define SUBTARGET_EXTRA_SPECS \
- { "netbsd_cpp_spec", NETBSD_CPP_SPEC }, \
- { "netbsd_link_spec", NETBSD_LINK_SPEC_AOUT },
-
-#undef CPP_SPEC
-#define CPP_SPEC "\
-%(cpp_cpu_arch) %(cpp_float) %(cpp_endian) %(netbsd_cpp_spec) \
-"
-
-/* Because TARGET_DEFAULT sets MASK_SOFT_FLOAT */
-#undef CPP_FLOAT_DEFAULT_SPEC
-#define CPP_FLOAT_DEFAULT_SPEC "-D__SOFTFP__"
-
-/* Pass -X to the linker so that it will strip symbols starting with 'L' */
-#undef LINK_SPEC
-#define LINK_SPEC "-X %(netbsd_link_spec)"
-
-#undef SIZE_TYPE
-#define SIZE_TYPE "unsigned int"
-
-#undef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "int"
-
-#define HANDLE_SYSV_PRAGMA 1
-
-/* We don't have any limit on the length as out debugger is GDB. */
-#undef DBX_CONTIN_LENGTH
-
-/* NetBSD does its profiling differently to the Acorn compiler. We
- don't need a word following the mcount call; and to skip it
- requires either an assembly stub or use of fomit-frame-pointer when
- compiling the profiling functions. Since we break Acorn CC
- compatibility below a little more won't hurt. */
-
-#undef ARM_FUNCTION_PROFILER
-#define ARM_FUNCTION_PROFILER(STREAM,LABELNO) \
-{ \
- fprintf(STREAM, "\tmov\t%sip, %slr\n", REGISTER_PREFIX, REGISTER_PREFIX); \
- fprintf(STREAM, "\tbl\tmcount\n"); \
-}
-
-/* On the ARM `@' introduces a comment, so we must use something else
- for .type directives. */
-#undef TYPE_OPERAND_FMT
-#define TYPE_OPERAND_FMT "%%%s"
-
-/* NetBSD uses the old PCC style aggregate returning conventions. */
-#undef DEFAULT_PCC_STRUCT_RETURN
-#define DEFAULT_PCC_STRUCT_RETURN 1
-
-/* Although not normally relevant (since by default, all aggregates
- are returned in memory) compiling some parts of libc requires
- non-APCS style struct returns. */
-#undef RETURN_IN_MEMORY
-
-/* VERY BIG NOTE : Change of structure alignment for RiscBSD.
- There are consequences you should be aware of...
-
- Normally GCC/arm uses a structure alignment of 32 for compatibility
- with armcc. This means that structures are padded to a word
- boundary. However this causes problems with bugged NetBSD kernel
- code (possibly userland code as well - I have not checked every
- binary). The nature of this bugged code is to rely on sizeof()
- returning the correct size of various structures rounded to the
- nearest byte (SCSI and ether code are two examples, the vm system
- is another). This code breaks when the structure alignment is 32
- as sizeof() will report a word=rounded size. By changing the
- structure alignment to 8. GCC will conform to what is expected by
- NetBSD.
-
- This has several side effects that should be considered.
- 1. Structures will only be aligned to the size of the largest member.
- i.e. structures containing only bytes will be byte aligned.
- structures containing shorts will be half word aligned.
- structures containing ints will be word aligned.
-
- This means structures should be padded to a word boundary if
- alignment of 32 is required for byte structures etc.
-
- 2. A potential performance penalty may exist if strings are no longer
- word aligned. GCC will not be able to use word load/stores to copy
- short strings.
-
- This modification is not encouraged but with the present state of the
- NetBSD source tree it is currently the only solution that meets the
- requirements. */
-#undef DEFAULT_STRUCTURE_SIZE_BOUNDARY
-#define DEFAULT_STRUCTURE_SIZE_BOUNDARY 8
-
-/* Clear the instruction cache from `BEG' to `END'. This makes a
- call to the ARM32_SYNC_ICACHE architecture specific syscall. */
-#define CLEAR_INSN_CACHE(BEG, END) \
-{ \
- extern int sysarch(int number, void *args); \
- struct { \
- unsigned int addr; \
- int len; \
- } s; \
- s.addr = (unsigned int)(BEG); \
- s.len = (END) - (BEG); \
- (void)sysarch(0, &s); \
-}
diff --git a/gcc-4.2.1/gcc/config/arm/pe.c b/gcc-4.2.1/gcc/config/arm/pe.c
deleted file mode 100644
index f2f67d5a9..000000000
--- a/gcc-4.2.1/gcc/config/arm/pe.c
+++ /dev/null
@@ -1,269 +0,0 @@
-/* Routines for GCC for ARM/pe.
- Copyright (C) 1995, 1996, 2000, 2001, 2002, 2004, 2005
- Free Software Foundation, Inc.
- Contributed by Doug Evans (dje@cygnus.com).
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "rtl.h"
-#include "output.h"
-#include "flags.h"
-#include "tree.h"
-#include "expr.h"
-#include "toplev.h"
-#include "tm_p.h"
-
-extern int current_function_anonymous_args;
-
-
-/* Return nonzero if DECL is a dllexport'd object. */
-
-tree current_class_type; /* FIXME */
-
-int
-arm_dllexport_p (decl)
- tree decl;
-{
- tree exp;
-
- if (TREE_CODE (decl) != VAR_DECL
- && TREE_CODE (decl) != FUNCTION_DECL)
- return 0;
- exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl));
- if (exp)
- return 1;
-
- return 0;
-}
-
-/* Return nonzero if DECL is a dllimport'd object. */
-
-int
-arm_dllimport_p (decl)
- tree decl;
-{
- tree imp;
-
- if (TREE_CODE (decl) == FUNCTION_DECL
- && TARGET_NOP_FUN_DLLIMPORT)
- return 0;
-
- if (TREE_CODE (decl) != VAR_DECL
- && TREE_CODE (decl) != FUNCTION_DECL)
- return 0;
- imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
- if (imp)
- return 1;
-
- return 0;
-}
-
-/* Return nonzero if SYMBOL is marked as being dllexport'd. */
-
-int
-arm_dllexport_name_p (symbol)
- const char * symbol;
-{
- return symbol[0] == ARM_PE_FLAG_CHAR && symbol[1] == 'e' && symbol[2] == '.';
-}
-
-/* Return nonzero if SYMBOL is marked as being dllimport'd. */
-
-int
-arm_dllimport_name_p (symbol)
- const char * symbol;
-{
- return symbol[0] == ARM_PE_FLAG_CHAR && symbol[1] == 'i' && symbol[2] == '.';
-}
-
-/* Mark a DECL as being dllexport'd.
- Note that we override the previous setting (e.g.: dllimport). */
-
-void
-arm_mark_dllexport (decl)
- tree decl;
-{
- const char * oldname;
- char * newname;
- rtx rtlname;
- tree idp;
-
- rtlname = XEXP (DECL_RTL (decl), 0);
- if (GET_CODE (rtlname) == MEM)
- rtlname = XEXP (rtlname, 0);
- gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
- oldname = XSTR (rtlname, 0);
-
- if (arm_dllimport_name_p (oldname))
- oldname += 9;
- else if (arm_dllexport_name_p (oldname))
- return; /* already done */
-
- newname = alloca (strlen (oldname) + 4);
- sprintf (newname, "%ce.%s", ARM_PE_FLAG_CHAR, oldname);
-
- /* We pass newname through get_identifier to ensure it has a unique
- address. RTL processing can sometimes peek inside the symbol ref
- and compare the string's addresses to see if two symbols are
- identical. */
- /* ??? At least I think that's why we do this. */
- idp = get_identifier (newname);
-
- XEXP (DECL_RTL (decl), 0) =
- gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
-}
-
-/* Mark a DECL as being dllimport'd. */
-
-void
-arm_mark_dllimport (decl)
- tree decl;
-{
- const char * oldname;
- char * newname;
- tree idp;
- rtx rtlname, newrtl;
-
- rtlname = XEXP (DECL_RTL (decl), 0);
-
- if (GET_CODE (rtlname) == MEM)
- rtlname = XEXP (rtlname, 0);
- gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
- oldname = XSTR (rtlname, 0);
-
- gcc_assert (!arm_dllexport_name_p (oldname));
- if (arm_dllimport_name_p (oldname))
- return; /* already done */
-
- /* ??? One can well ask why we're making these checks here,
- and that would be a good question. */
-
- /* Imported variables can't be initialized. */
- if (TREE_CODE (decl) == VAR_DECL
- && !DECL_VIRTUAL_P (decl)
- && DECL_INITIAL (decl))
- {
- error ("initialized variable %q+D is marked dllimport", decl);
- return;
- }
- /* Nor can they be static. */
- if (TREE_CODE (decl) == VAR_DECL
- /* ??? Is this test for vtables needed? */
- && !DECL_VIRTUAL_P (decl)
- && 0 /*???*/)
- {
- error ("static variable %q+D is marked dllimport", decl);
- return;
- }
-
- /* `extern' needn't be specified with dllimport.
- Specify `extern' now and hope for the best. Sigh. */
- if (TREE_CODE (decl) == VAR_DECL
- /* ??? Is this test for vtables needed? */
- && !DECL_VIRTUAL_P (decl))
- {
- DECL_EXTERNAL (decl) = 1;
- TREE_PUBLIC (decl) = 1;
- }
-
- newname = alloca (strlen (oldname) + 11);
- sprintf (newname, "%ci.__imp_%s", ARM_PE_FLAG_CHAR, oldname);
-
- /* We pass newname through get_identifier to ensure it has a unique
- address. RTL processing can sometimes peek inside the symbol ref
- and compare the string's addresses to see if two symbols are
- identical. */
- /* ??? At least I think that's why we do this. */
- idp = get_identifier (newname);
-
- newrtl = gen_rtx_MEM (Pmode,
- gen_rtx_SYMBOL_REF (Pmode,
- IDENTIFIER_POINTER (idp)));
- XEXP (DECL_RTL (decl), 0) = newrtl;
-}
-
-void
-arm_pe_encode_section_info (decl, rtl, first)
- tree decl;
- rtx rtl;
- int first ATTRIBUTE_UNUSED;
-{
- /* This bit is copied from arm_encode_section_info. */
- if (optimize > 0 && TREE_CONSTANT (decl))
- SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
-
- /* Mark the decl so we can tell from the rtl whether the object is
- dllexport'd or dllimport'd. */
- if (arm_dllexport_p (decl))
- arm_mark_dllexport (decl);
- else if (arm_dllimport_p (decl))
- arm_mark_dllimport (decl);
- /* It might be that DECL has already been marked as dllimport, but a
- subsequent definition nullified that. The attribute is gone but
- DECL_RTL still has @i.__imp_foo. We need to remove that. */
- else if ((TREE_CODE (decl) == FUNCTION_DECL
- || TREE_CODE (decl) == VAR_DECL)
- && DECL_RTL (decl) != NULL_RTX
- && GET_CODE (DECL_RTL (decl)) == MEM
- && GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM
- && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF
- && arm_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0)))
- {
- const char *oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0);
- tree idp = get_identifier (oldname + 9);
- rtx newrtl = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
-
- XEXP (DECL_RTL (decl), 0) = newrtl;
-
- /* We previously set TREE_PUBLIC and DECL_EXTERNAL.
- ??? We leave these alone for now. */
- }
-}
-
-void
-arm_pe_unique_section (decl, reloc)
- tree decl;
- int reloc;
-{
- int len;
- const char * name;
- char * string;
- const char * prefix;
-
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- name = arm_strip_name_encoding (name);
-
- /* The object is put in, for example, section .text$foo.
- The linker will then ultimately place them in .text
- (everything from the $ on is stripped). */
- if (TREE_CODE (decl) == FUNCTION_DECL)
- prefix = ".text$";
- else if (decl_readonly_section (decl, reloc))
- prefix = ".rdata$";
- else
- prefix = ".data$";
- len = strlen (name) + strlen (prefix);
- string = alloca (len + 1);
- sprintf (string, "%s%s", prefix, name);
-
- DECL_SECTION_NAME (decl) = build_string (len, string);
-}
diff --git a/gcc-4.2.1/gcc/config/arm/pe.h b/gcc-4.2.1/gcc/config/arm/pe.h
deleted file mode 100644
index f96cd66a9..000000000
--- a/gcc-4.2.1/gcc/config/arm/pe.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/* Definitions of target machine for GNU compiler, for ARM with PE obj format.
- Copyright (C) 1995, 1996, 1999, 2000, 2002, 2003, 2004, 2005
- Free Software Foundation, Inc.
- Contributed by Doug Evans (dje@cygnus.com).
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* Enable PE specific code. */
-#define ARM_PE 1
-
-#define ARM_PE_FLAG_CHAR '@'
-
-/* Ensure that @x. will be stripped from the function name. */
-#undef SUBTARGET_NAME_ENCODING_LENGTHS
-#define SUBTARGET_NAME_ENCODING_LENGTHS \
- case ARM_PE_FLAG_CHAR: return 3;
-
-#undef USER_LABEL_PREFIX
-#define USER_LABEL_PREFIX "_"
-
-
-/* Run-time Target Specification. */
-#undef TARGET_VERSION
-#define TARGET_VERSION fputs (" (ARM/pe)", stderr)
-
-/* Get tree.c to declare a target-specific specialization of
- merge_decl_attributes. */
-#define TARGET_DLLIMPORT_DECL_ATTRIBUTES 1
-
-#undef SUBTARGET_CPP_SPEC
-#define SUBTARGET_CPP_SPEC "-D__pe__"
-
-#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_NOP_FUN_DLLIMPORT)
-
-#undef MULTILIB_DEFAULTS
-#define MULTILIB_DEFAULTS \
- { "marm", "mlittle-endian", "msoft-float", "mno-thumb-interwork" }
-
-#undef WCHAR_TYPE
-#define WCHAR_TYPE "short unsigned int"
-#undef WCHAR_TYPE_SIZE
-#define WCHAR_TYPE_SIZE 16
-
-/* r11 is fixed. */
-#undef SUBTARGET_CONDITIONAL_REGISTER_USAGE
-#define SUBTARGET_CONDITIONAL_REGISTER_USAGE \
- fixed_regs [11] = 1; \
- call_used_regs [11] = 1;
-
-
-/* PE/COFF uses explicit import from shared libraries. */
-#define MULTIPLE_SYMBOL_SPACES 1
-
-#define TARGET_ASM_UNIQUE_SECTION arm_pe_unique_section
-#define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
-
-#define SUPPORTS_ONE_ONLY 1
-
-/* Switch into a generic section. */
-#undef TARGET_ASM_NAMED_SECTION
-#define TARGET_ASM_NAMED_SECTION default_pe_asm_named_section
-
-#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
-
-/* Output a reference to a label. */
-#undef ASM_OUTPUT_LABELREF
-#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
- asm_fprintf (STREAM, "%U%s", arm_strip_name_encoding (NAME))
-
-/* Output a function definition label. */
-#undef ASM_DECLARE_FUNCTION_NAME
-#define ASM_DECLARE_FUNCTION_NAME(STREAM, NAME, DECL) \
- do \
- { \
- if (arm_dllexport_name_p (NAME)) \
- { \
- drectve_section (); \
- fprintf (STREAM, "\t.ascii \" -export:%s\"\n", \
- arm_strip_name_encoding (NAME)); \
- switch_to_section (function_section (DECL)); \
- } \
- ARM_DECLARE_FUNCTION_NAME (STREAM, NAME, DECL); \
- if (TARGET_THUMB) \
- fprintf (STREAM, "\t.code 16\n"); \
- ASM_OUTPUT_LABEL (STREAM, NAME); \
- } \
- while (0)
-
-/* Output a common block. */
-#undef ASM_OUTPUT_COMMON
-#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \
- do \
- { \
- if (arm_dllexport_name_p (NAME)) \
- { \
- drectve_section (); \
- fprintf ((STREAM), "\t.ascii \" -export:%s\"\n",\
- arm_strip_name_encoding (NAME)); \
- } \
- if (! arm_dllimport_name_p (NAME)) \
- { \
- fprintf ((STREAM), "\t.comm\t"); \
- assemble_name ((STREAM), (NAME)); \
- asm_fprintf ((STREAM), ", %d\t%@ %d\n", \
- (int)(ROUNDED), (int)(SIZE)); \
- } \
- } \
- while (0)
-
-/* Output the label for an initialized variable. */
-#undef ASM_DECLARE_OBJECT_NAME
-#define ASM_DECLARE_OBJECT_NAME(STREAM, NAME, DECL) \
- do \
- { \
- if (arm_dllexport_name_p (NAME)) \
- { \
- section *save_section = in_section; \
- drectve_section (); \
- fprintf (STREAM, "\t.ascii \" -export:%s\"\n",\
- arm_strip_name_encoding (NAME)); \
- switch_to_section (save_section); \
- } \
- ASM_OUTPUT_LABEL ((STREAM), (NAME)); \
- } \
- while (0)
-
-/* Support the ctors/dtors and other sections. */
-
-#define DRECTVE_SECTION_ASM_OP "\t.section .drectve"
-
-#define drectve_section() \
- (fprintf (asm_out_file, "%s\n", DRECTVE_SECTION_ASM_OP), \
- in_section = NULL)
diff --git a/gcc-4.2.1/gcc/config/arm/pe.opt b/gcc-4.2.1/gcc/config/arm/pe.opt
deleted file mode 100644
index f3d6d8b53..000000000
--- a/gcc-4.2.1/gcc/config/arm/pe.opt
+++ /dev/null
@@ -1,24 +0,0 @@
-; PE-specific options for the ARM port
-
-; Copyright (C) 2005 Free Software Foundation, Inc.
-;
-; This file is part of GCC.
-;
-; GCC is free software; you can redistribute it and/or modify it under
-; the terms of the GNU General Public License as published by the Free
-; Software Foundation; either version 2, or (at your option) any later
-; version.
-;
-; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-; WARRANTY; without even the implied warranty of MERCHANTABILITY or
-; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-; for more details.
-;
-; You should have received a copy of the GNU General Public License
-; along with GCC; see the file COPYING. If not, write to the Free
-; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-; 02110-1301, USA.
-
-mnop-fun-dllimport
-Target Report Mask(NOP_FUN_DLLIMPORT)
-Ignore dllimport attribute for functions
diff --git a/gcc-4.2.1/gcc/config/arm/pr-support.c b/gcc-4.2.1/gcc/config/arm/pr-support.c
deleted file mode 100644
index 0e750bf3e..000000000
--- a/gcc-4.2.1/gcc/config/arm/pr-support.c
+++ /dev/null
@@ -1,381 +0,0 @@
-/* ARM EABI compliant unwinding routines
- Copyright (C) 2004, 2005 Free Software Foundation, Inc.
- Contributed by Paul Brook
-
- 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 into combinations with other programs,
- and to distribute those combinations 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 a combine
- executable.)
-
- 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, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-#include "unwind.h"
-
-/* We add a prototype for abort here to avoid creating a dependency on
- target headers. */
-extern void abort (void);
-
-typedef struct _ZSt9type_info type_info; /* This names C++ type_info type */
-
-/* Misc constants. */
-#define R_IP 12
-#define R_SP 13
-#define R_LR 14
-#define R_PC 15
-
-#define uint32_highbit (((_uw) 1) << 31)
-
-void __attribute__((weak)) __cxa_call_unexpected(_Unwind_Control_Block *ucbp);
-
-/* Unwind descriptors. */
-
-typedef struct
-{
- _uw16 length;
- _uw16 offset;
-} EHT16;
-
-typedef struct
-{
- _uw length;
- _uw offset;
-} EHT32;
-
-/* Calculate the address encoded by a 31-bit self-relative offset at address
- P. Copy of routine in unwind-arm.c. */
-
-static inline _uw
-selfrel_offset31 (const _uw *p)
-{
- _uw offset;
-
- offset = *p;
- /* Sign extend to 32 bits. */
- if (offset & (1 << 30))
- offset |= 1u << 31;
-
- return offset + (_uw) p;
-}
-
-
-/* Personality routine helper functions. */
-
-#define CODE_FINISH (0xb0)
-
-/* Return the next byte of unwinding information, or CODE_FINISH if there is
- no data remaining. */
-static inline _uw8
-next_unwind_byte (__gnu_unwind_state * uws)
-{
- _uw8 b;
-
- if (uws->bytes_left == 0)
- {
- /* Load another word */
- if (uws->words_left == 0)
- return CODE_FINISH; /* Nothing left. */
- uws->words_left--;
- uws->data = *(uws->next++);
- uws->bytes_left = 3;
- }
- else
- uws->bytes_left--;
-
- /* Extract the most significant byte. */
- b = (uws->data >> 24) & 0xff;
- uws->data <<= 8;
- return b;
-}
-
-/* Execute the unwinding instructions described by UWS. */
-_Unwind_Reason_Code
-__gnu_unwind_execute (_Unwind_Context * context, __gnu_unwind_state * uws)
-{
- _uw op;
- int set_pc;
- _uw reg;
-
- set_pc = 0;
- for (;;)
- {
- op = next_unwind_byte (uws);
- if (op == CODE_FINISH)
- {
- /* If we haven't already set pc then copy it from lr. */
- if (!set_pc)
- {
- _Unwind_VRS_Get (context, _UVRSC_CORE, R_LR, _UVRSD_UINT32,
- &reg);
- _Unwind_VRS_Set (context, _UVRSC_CORE, R_PC, _UVRSD_UINT32,
- &reg);
- set_pc = 1;
- }
- /* Drop out of the loop. */
- break;
- }
- if ((op & 0x80) == 0)
- {
- /* vsp = vsp +- (imm6 << 2 + 4). */
- _uw offset;
-
- offset = ((op & 0x3f) << 2) + 4;
- _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
- if (op & 0x40)
- reg -= offset;
- else
- reg += offset;
- _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
- continue;
- }
-
- if ((op & 0xf0) == 0x80)
- {
- op = (op << 8) | next_unwind_byte (uws);
- if (op == 0x8000)
- {
- /* Refuse to unwind. */
- return _URC_FAILURE;
- }
- /* Pop r4-r15 under mask. */
- op = (op << 4) & 0xfff0;
- if (_Unwind_VRS_Pop (context, _UVRSC_CORE, op, _UVRSD_UINT32)
- != _UVRSR_OK)
- return _URC_FAILURE;
- if (op & (1 << R_PC))
- set_pc = 1;
- continue;
- }
- if ((op & 0xf0) == 0x90)
- {
- op &= 0xf;
- if (op == 13 || op == 15)
- /* Reserved. */
- return _URC_FAILURE;
- /* vsp = r[nnnn]. */
- _Unwind_VRS_Get (context, _UVRSC_CORE, op, _UVRSD_UINT32, &reg);
- _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
- continue;
- }
- if ((op & 0xf0) == 0xa0)
- {
- /* Pop r4-r[4+nnn], [lr]. */
- _uw mask;
-
- mask = (0xff0 >> (7 - (op & 7))) & 0xff0;
- if (op & 8)
- mask |= (1 << R_LR);
- if (_Unwind_VRS_Pop (context, _UVRSC_CORE, mask, _UVRSD_UINT32)
- != _UVRSR_OK)
- return _URC_FAILURE;
- continue;
- }
- if ((op & 0xf0) == 0xb0)
- {
- /* op == 0xb0 already handled. */
- if (op == 0xb1)
- {
- op = next_unwind_byte (uws);
- if (op == 0 || ((op & 0xf0) != 0))
- /* Spare. */
- return _URC_FAILURE;
- /* Pop r0-r4 under mask. */
- if (_Unwind_VRS_Pop (context, _UVRSC_CORE, op, _UVRSD_UINT32)
- != _UVRSR_OK)
- return _URC_FAILURE;
- continue;
- }
- if (op == 0xb2)
- {
- /* vsp = vsp + 0x204 + (uleb128 << 2). */
- int shift;
-
- _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32,
- &reg);
- op = next_unwind_byte (uws);
- shift = 2;
- while (op & 0x80)
- {
- reg += ((op & 0x7f) << shift);
- shift += 7;
- op = next_unwind_byte (uws);
- }
- reg += ((op & 0x7f) << shift) + 0x204;
- _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32,
- &reg);
- continue;
- }
- if (op == 0xb3)
- {
- /* Pop VFP registers with fldmx. */
- op = next_unwind_byte (uws);
- op = ((op & 0xf0) << 12) | ((op & 0xf) + 1);
- if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_VFPX)
- != _UVRSR_OK)
- return _URC_FAILURE;
- continue;
- }
- if ((op & 0xfc) == 0xb4)
- {
- /* Pop FPA E[4]-E[4+nn]. */
- op = 0x40000 | ((op & 3) + 1);
- if (_Unwind_VRS_Pop (context, _UVRSC_FPA, op, _UVRSD_FPAX)
- != _UVRSR_OK)
- return _URC_FAILURE;
- continue;
- }
- /* op & 0xf8 == 0xb8. */
- /* Pop VFP D[8]-D[8+nnn] with fldmx. */
- op = 0x80000 | ((op & 7) + 1);
- if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_VFPX)
- != _UVRSR_OK)
- return _URC_FAILURE;
- continue;
- }
- if ((op & 0xf0) == 0xc0)
- {
- if (op == 0xc6)
- {
- /* Pop iWMMXt D registers. */
- op = next_unwind_byte (uws);
- op = ((op & 0xf0) << 12) | ((op & 0xf) + 1);
- if (_Unwind_VRS_Pop (context, _UVRSC_WMMXD, op, _UVRSD_UINT64)
- != _UVRSR_OK)
- return _URC_FAILURE;
- continue;
- }
- if (op == 0xc7)
- {
- op = next_unwind_byte (uws);
- if (op == 0 || (op & 0xf0) != 0)
- /* Spare. */
- return _URC_FAILURE;
- /* Pop iWMMXt wCGR{3,2,1,0} under mask. */
- if (_Unwind_VRS_Pop (context, _UVRSC_WMMXC, op, _UVRSD_UINT32)
- != _UVRSR_OK)
- return _URC_FAILURE;
- continue;
- }
- if ((op & 0xf8) == 0xc0)
- {
- /* Pop iWMMXt wR[10]-wR[10+nnn]. */
- op = 0xa0000 | ((op & 0xf) + 1);
- if (_Unwind_VRS_Pop (context, _UVRSC_WMMXD, op, _UVRSD_UINT64)
- != _UVRSR_OK)
- return _URC_FAILURE;
- continue;
- }
- if (op == 0xc8)
- {
- /* Pop FPA registers. */
- op = next_unwind_byte (uws);
- op = ((op & 0xf0) << 12) | ((op & 0xf) + 1);
- if (_Unwind_VRS_Pop (context, _UVRSC_FPA, op, _UVRSD_FPAX)
- != _UVRSR_OK)
- return _URC_FAILURE;
- continue;
- }
- if (op == 0xc9)
- {
- /* Pop VFP registers with fldmd. */
- op = next_unwind_byte (uws);
- op = ((op & 0xf0) << 12) | ((op & 0xf) + 1);
- if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_DOUBLE)
- != _UVRSR_OK)
- return _URC_FAILURE;
- continue;
- }
- /* Spare. */
- return _URC_FAILURE;
- }
- if ((op & 0xf8) == 0xd0)
- {
- /* Pop VFP D[8]-D[8+nnn] with fldmd. */
- op = 0x80000 | ((op & 7) + 1);
- if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_DOUBLE)
- != _UVRSR_OK)
- return _URC_FAILURE;
- continue;
- }
- /* Spare. */
- return _URC_FAILURE;
- }
- return _URC_OK;
-}
-
-
-/* Execute the unwinding instructions associated with a frame. UCBP and
- CONTEXT are the current exception object and virtual CPU state
- respectively. */
-
-_Unwind_Reason_Code
-__gnu_unwind_frame (_Unwind_Control_Block * ucbp, _Unwind_Context * context)
-{
- _uw *ptr;
- __gnu_unwind_state uws;
-
- ptr = (_uw *) ucbp->pr_cache.ehtp;
- /* Skip over the personality routine address. */
- ptr++;
- /* Setup the unwinder state. */
- uws.data = (*ptr) << 8;
- uws.next = ptr + 1;
- uws.bytes_left = 3;
- uws.words_left = ((*ptr) >> 24) & 0xff;
-
- return __gnu_unwind_execute (context, &uws);
-}
-
-/* Get the _Unwind_Control_Block from an _Unwind_Context. */
-
-static inline _Unwind_Control_Block *
-unwind_UCB_from_context (_Unwind_Context * context)
-{
- return (_Unwind_Control_Block *) _Unwind_GetGR (context, R_IP);
-}
-
-/* Get the start address of the function being unwound. */
-
-_Unwind_Ptr
-_Unwind_GetRegionStart (_Unwind_Context * context)
-{
- _Unwind_Control_Block *ucbp;
-
- ucbp = unwind_UCB_from_context (context);
- return (_Unwind_Ptr) ucbp->pr_cache.fnstart;
-}
-
-/* Find the Language specific exception data. */
-
-void *
-_Unwind_GetLanguageSpecificData (_Unwind_Context * context)
-{
- _Unwind_Control_Block *ucbp;
- _uw *ptr;
-
- /* Get a pointer to the exception table entry. */
- ucbp = unwind_UCB_from_context (context);
- ptr = (_uw *) ucbp->pr_cache.ehtp;
- /* Skip the personality routine address. */
- ptr++;
- /* Skip the unwind opcodes. */
- ptr += (((*ptr) >> 24) & 0xff) + 1;
-
- return ptr;
-}
-
diff --git a/gcc-4.2.1/gcc/config/arm/predicates.md b/gcc-4.2.1/gcc/config/arm/predicates.md
deleted file mode 100644
index 4a08204d1..000000000
--- a/gcc-4.2.1/gcc/config/arm/predicates.md
+++ /dev/null
@@ -1,458 +0,0 @@
-;; Predicate definitions for ARM and Thumb
-;; Copyright (C) 2004 Free Software Foundation, Inc.
-;; Contributed by ARM Ltd.
-
-;; This file is part of GCC.
-
-;; GCC is free software; you can redistribute it and/or modify it
-;; under the terms of the GNU General Public License as published
-;; by the Free Software Foundation; either version 2, or (at your
-;; option) any later version.
-
-;; GCC is distributed in the hope that it will be useful, but WITHOUT
-;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
-;; License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
-
-(define_predicate "s_register_operand"
- (match_code "reg,subreg")
-{
- 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));
-})
-
-;; Any hard register.
-(define_predicate "arm_hard_register_operand"
- (match_code "reg")
-{
- return REGNO (op) < FIRST_PSEUDO_REGISTER;
-})
-
-;; Any core register, or any pseudo. */
-(define_predicate "arm_general_register_operand"
- (match_code "reg,subreg")
-{
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
-
- return (GET_CODE (op) == REG
- && (REGNO (op) <= LAST_ARM_REGNUM
- || REGNO (op) >= FIRST_PSEUDO_REGISTER));
-})
-
-(define_predicate "f_register_operand"
- (match_code "reg,subreg")
-{
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
-
- /* We don't consider registers whose class is NO_REGS
- to be a register operand. */
- return (GET_CODE (op) == REG
- && (REGNO (op) >= FIRST_PSEUDO_REGISTER
- || REGNO_REG_CLASS (REGNO (op)) == FPA_REGS));
-})
-
-;; Reg, subreg(reg) or const_int.
-(define_predicate "reg_or_int_operand"
- (ior (match_code "const_int")
- (match_operand 0 "s_register_operand")))
-
-(define_predicate "arm_immediate_operand"
- (and (match_code "const_int")
- (match_test "const_ok_for_arm (INTVAL (op))")))
-
-(define_predicate "arm_neg_immediate_operand"
- (and (match_code "const_int")
- (match_test "const_ok_for_arm (-INTVAL (op))")))
-
-(define_predicate "arm_not_immediate_operand"
- (and (match_code "const_int")
- (match_test "const_ok_for_arm (~INTVAL (op))")))
-
-;; Something valid on the RHS of an ARM data-processing instruction
-(define_predicate "arm_rhs_operand"
- (ior (match_operand 0 "s_register_operand")
- (match_operand 0 "arm_immediate_operand")))
-
-(define_predicate "arm_rhsm_operand"
- (ior (match_operand 0 "arm_rhs_operand")
- (match_operand 0 "memory_operand")))
-
-(define_predicate "arm_add_operand"
- (ior (match_operand 0 "arm_rhs_operand")
- (match_operand 0 "arm_neg_immediate_operand")))
-
-(define_predicate "arm_addimm_operand"
- (ior (match_operand 0 "arm_immediate_operand")
- (match_operand 0 "arm_neg_immediate_operand")))
-
-(define_predicate "arm_not_operand"
- (ior (match_operand 0 "arm_rhs_operand")
- (match_operand 0 "arm_not_immediate_operand")))
-
-;; True if the operand is a memory reference which contains an
-;; offsettable address.
-(define_predicate "offsettable_memory_operand"
- (and (match_code "mem")
- (match_test
- "offsettable_address_p (reload_completed | reload_in_progress,
- mode, XEXP (op, 0))")))
-
-;; True if the operand is a memory operand that does not have an
-;; automodified base register (and thus will not generate output reloads).
-(define_predicate "call_memory_operand"
- (and (match_code "mem")
- (and (match_test "GET_RTX_CLASS (GET_CODE (XEXP (op, 0)))
- != RTX_AUTOINC")
- (match_operand 0 "memory_operand"))))
-
-(define_predicate "arm_reload_memory_operand"
- (and (match_code "mem,reg,subreg")
- (match_test "(!CONSTANT_P (op)
- && (true_regnum(op) == -1
- || (GET_CODE (op) == REG
- && REGNO (op) >= FIRST_PSEUDO_REGISTER)))")))
-
-;; True for valid operands for the rhs of an floating point insns.
-;; Allows regs or certain consts on FPA, just regs for everything else.
-(define_predicate "arm_float_rhs_operand"
- (ior (match_operand 0 "s_register_operand")
- (and (match_code "const_double")
- (match_test "TARGET_FPA && arm_const_double_rtx (op)"))))
-
-(define_predicate "arm_float_add_operand"
- (ior (match_operand 0 "arm_float_rhs_operand")
- (and (match_code "const_double")
- (match_test "TARGET_FPA && neg_const_double_rtx_ok_for_fpa (op)"))))
-
-(define_predicate "vfp_compare_operand"
- (ior (match_operand 0 "s_register_operand")
- (and (match_code "const_double")
- (match_test "arm_const_double_rtx (op)"))))
-
-(define_predicate "arm_float_compare_operand"
- (if_then_else (match_test "TARGET_VFP")
- (match_operand 0 "vfp_compare_operand")
- (match_operand 0 "arm_float_rhs_operand")))
-
-;; True for valid index operands.
-(define_predicate "index_operand"
- (ior (match_operand 0 "s_register_operand")
- (and (match_operand 0 "immediate_operand")
- (match_test "(GET_CODE (op) != CONST_INT
- || (INTVAL (op) < 4096 && INTVAL (op) > -4096))"))))
-
-;; True for operators that can be combined with a shift in ARM state.
-(define_special_predicate "shiftable_operator"
- (and (match_code "plus,minus,ior,xor,and")
- (match_test "mode == GET_MODE (op)")))
-
-;; True for logical binary operators.
-(define_special_predicate "logical_binary_operator"
- (and (match_code "ior,xor,and")
- (match_test "mode == GET_MODE (op)")))
-
-;; True for shift operators.
-(define_special_predicate "shift_operator"
- (and (ior (ior (and (match_code "mult")
- (match_test "power_of_two_operand (XEXP (op, 1), mode)"))
- (and (match_code "rotate")
- (match_test "GET_CODE (XEXP (op, 1)) == CONST_INT
- && ((unsigned HOST_WIDE_INT) INTVAL (XEXP (op, 1))) < 32")))
- (match_code "ashift,ashiftrt,lshiftrt,rotatert"))
- (match_test "mode == GET_MODE (op)")))
-
-;; True for EQ & NE
-(define_special_predicate "equality_operator"
- (match_code "eq,ne"))
-
-;; True for comparisons other than LTGT or UNEQ.
-(define_special_predicate "arm_comparison_operator"
- (match_code "eq,ne,le,lt,ge,gt,geu,gtu,leu,ltu,unordered,ordered,unlt,unle,unge,ungt"))
-
-(define_special_predicate "minmax_operator"
- (and (match_code "smin,smax,umin,umax")
- (match_test "mode == GET_MODE (op)")))
-
-(define_special_predicate "cc_register"
- (and (match_code "reg")
- (and (match_test "REGNO (op) == CC_REGNUM")
- (ior (match_test "mode == GET_MODE (op)")
- (match_test "mode == VOIDmode && GET_MODE_CLASS (GET_MODE (op)) == MODE_CC")))))
-
-(define_special_predicate "dominant_cc_register"
- (match_code "reg")
-{
- if (mode == VOIDmode)
- {
- mode = GET_MODE (op);
-
- if (GET_MODE_CLASS (mode) != MODE_CC)
- return false;
- }
-
- return (cc_register (op, mode)
- && (mode == CC_DNEmode
- || mode == CC_DEQmode
- || mode == CC_DLEmode
- || mode == CC_DLTmode
- || mode == CC_DGEmode
- || mode == CC_DGTmode
- || mode == CC_DLEUmode
- || mode == CC_DLTUmode
- || mode == CC_DGEUmode
- || mode == CC_DGTUmode));
-})
-
-(define_special_predicate "arm_extendqisi_mem_op"
- (and (match_operand 0 "memory_operand")
- (match_test "arm_legitimate_address_p (mode, XEXP (op, 0), SIGN_EXTEND,
- 0)")))
-
-(define_predicate "power_of_two_operand"
- (match_code "const_int")
-{
- HOST_WIDE_INT value = INTVAL (op);
-
- return value != 0 && (value & (value - 1)) == 0;
-})
-
-(define_predicate "nonimmediate_di_operand"
- (match_code "reg,subreg,mem")
-{
- if (s_register_operand (op, mode))
- return true;
-
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
-
- return GET_CODE (op) == MEM && memory_address_p (DImode, XEXP (op, 0));
-})
-
-(define_predicate "di_operand"
- (ior (match_code "const_int,const_double")
- (and (match_code "reg,subreg,mem")
- (match_operand 0 "nonimmediate_di_operand"))))
-
-(define_predicate "nonimmediate_soft_df_operand"
- (match_code "reg,subreg,mem")
-{
- if (s_register_operand (op, mode))
- return true;
-
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
-
- return GET_CODE (op) == MEM && memory_address_p (DFmode, XEXP (op, 0));
-})
-
-(define_predicate "soft_df_operand"
- (ior (match_code "const_double")
- (and (match_code "reg,subreg,mem")
- (match_operand 0 "nonimmediate_soft_df_operand"))))
-
-(define_predicate "const_shift_operand"
- (and (match_code "const_int")
- (ior (match_operand 0 "power_of_two_operand")
- (match_test "((unsigned HOST_WIDE_INT) INTVAL (op)) < 32"))))
-
-
-(define_special_predicate "load_multiple_operation"
- (match_code "parallel")
-{
- HOST_WIDE_INT count = XVECLEN (op, 0);
- int dest_regno;
- rtx src_addr;
- HOST_WIDE_INT i = 1, base = 0;
- rtx elt;
-
- if (count <= 1
- || GET_CODE (XVECEXP (op, 0, 0)) != SET)
- return false;
-
- /* Check to see if this might be a write-back. */
- if (GET_CODE (SET_SRC (elt = XVECEXP (op, 0, 0))) == PLUS)
- {
- i++;
- base = 1;
-
- /* Now check it more carefully. */
- if (GET_CODE (SET_DEST (elt)) != REG
- || GET_CODE (XEXP (SET_SRC (elt), 0)) != REG
- || GET_CODE (XEXP (SET_SRC (elt), 1)) != CONST_INT
- || INTVAL (XEXP (SET_SRC (elt), 1)) != (count - 1) * 4)
- return false;
- }
-
- /* Perform a quick check so we don't blow up below. */
- if (count <= i
- || GET_CODE (XVECEXP (op, 0, i - 1)) != SET
- || GET_CODE (SET_DEST (XVECEXP (op, 0, i - 1))) != REG
- || GET_CODE (SET_SRC (XVECEXP (op, 0, i - 1))) != MEM)
- return false;
-
- dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, i - 1)));
- src_addr = XEXP (SET_SRC (XVECEXP (op, 0, i - 1)), 0);
-
- for (; i < count; i++)
- {
- elt = XVECEXP (op, 0, i);
-
- if (GET_CODE (elt) != SET
- || GET_CODE (SET_DEST (elt)) != REG
- || GET_MODE (SET_DEST (elt)) != SImode
- || REGNO (SET_DEST (elt)) != (unsigned int)(dest_regno + i - base)
- || GET_CODE (SET_SRC (elt)) != MEM
- || GET_MODE (SET_SRC (elt)) != SImode
- || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
- || !rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
- || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
- || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != (i - base) * 4)
- return false;
- }
-
- return true;
-})
-
-(define_special_predicate "store_multiple_operation"
- (match_code "parallel")
-{
- HOST_WIDE_INT count = XVECLEN (op, 0);
- int src_regno;
- rtx dest_addr;
- HOST_WIDE_INT i = 1, base = 0;
- rtx elt;
-
- if (count <= 1
- || GET_CODE (XVECEXP (op, 0, 0)) != SET)
- return false;
-
- /* Check to see if this might be a write-back. */
- if (GET_CODE (SET_SRC (elt = XVECEXP (op, 0, 0))) == PLUS)
- {
- i++;
- base = 1;
-
- /* Now check it more carefully. */
- if (GET_CODE (SET_DEST (elt)) != REG
- || GET_CODE (XEXP (SET_SRC (elt), 0)) != REG
- || GET_CODE (XEXP (SET_SRC (elt), 1)) != CONST_INT
- || INTVAL (XEXP (SET_SRC (elt), 1)) != (count - 1) * 4)
- return false;
- }
-
- /* Perform a quick check so we don't blow up below. */
- if (count <= i
- || GET_CODE (XVECEXP (op, 0, i - 1)) != SET
- || GET_CODE (SET_DEST (XVECEXP (op, 0, i - 1))) != MEM
- || GET_CODE (SET_SRC (XVECEXP (op, 0, i - 1))) != REG)
- return false;
-
- src_regno = REGNO (SET_SRC (XVECEXP (op, 0, i - 1)));
- dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, i - 1)), 0);
-
- for (; i < count; i++)
- {
- elt = XVECEXP (op, 0, i);
-
- if (GET_CODE (elt) != SET
- || GET_CODE (SET_SRC (elt)) != REG
- || GET_MODE (SET_SRC (elt)) != SImode
- || REGNO (SET_SRC (elt)) != (unsigned int)(src_regno + i - base)
- || GET_CODE (SET_DEST (elt)) != MEM
- || GET_MODE (SET_DEST (elt)) != SImode
- || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
- || !rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
- || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
- || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != (i - base) * 4)
- return false;
- }
-
- return true;
-})
-
-(define_special_predicate "multi_register_push"
- (match_code "parallel")
-{
- if ((GET_CODE (XVECEXP (op, 0, 0)) != SET)
- || (GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC)
- || (XINT (SET_SRC (XVECEXP (op, 0, 0)), 1) != UNSPEC_PUSH_MULT))
- return false;
-
- return true;
-})
-
-;;-------------------------------------------------------------------------
-;;
-;; Thumb predicates
-;;
-
-(define_predicate "thumb_cmp_operand"
- (ior (and (match_code "reg,subreg")
- (match_operand 0 "s_register_operand"))
- (and (match_code "const_int")
- (match_test "((unsigned HOST_WIDE_INT) INTVAL (op)) < 256"))))
-
-(define_predicate "thumb_cmpneg_operand"
- (and (match_code "const_int")
- (match_test "INTVAL (op) < 0 && INTVAL (op) > -256")))
-
-;; Return TRUE if a result can be stored in OP without clobbering the
-;; condition code register. Prior to reload we only accept a
-;; register. After reload we have to be able to handle memory as
-;; well, since a pseudo may not get a hard reg and reload cannot
-;; handle output-reloads on jump insns.
-
-;; We could possibly handle mem before reload as well, but that might
-;; complicate things with the need to handle increment
-;; side-effects.
-(define_predicate "thumb_cbrch_target_operand"
- (and (match_code "reg,subreg,mem")
- (ior (match_operand 0 "s_register_operand")
- (and (match_test "reload_in_progress || reload_completed")
- (match_operand 0 "memory_operand")))))
-
-;;-------------------------------------------------------------------------
-;;
-;; MAVERICK predicates
-;;
-
-(define_predicate "cirrus_register_operand"
- (match_code "reg,subreg")
-{
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
-
- return (GET_CODE (op) == REG
- && (REGNO_REG_CLASS (REGNO (op)) == CIRRUS_REGS
- || REGNO_REG_CLASS (REGNO (op)) == GENERAL_REGS));
-})
-
-(define_predicate "cirrus_fp_register"
- (match_code "reg,subreg")
-{
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
-
- return (GET_CODE (op) == REG
- && (REGNO (op) >= FIRST_PSEUDO_REGISTER
- || REGNO_REG_CLASS (REGNO (op)) == CIRRUS_REGS));
-})
-
-(define_predicate "cirrus_shift_const"
- (and (match_code "const_int")
- (match_test "((unsigned HOST_WIDE_INT) INTVAL (op)) < 64")))
-
-
diff --git a/gcc-4.2.1/gcc/config/arm/rtems-elf.h b/gcc-4.2.1/gcc/config/arm/rtems-elf.h
deleted file mode 100644
index f71e582ed..000000000
--- a/gcc-4.2.1/gcc/config/arm/rtems-elf.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* Definitions for RTEMS based ARM systems using ELF
- Copyright (C) 2000, 2002, 2005 Free Software Foundation, Inc.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* Run-time Target Specification. */
-#undef TARGET_VERSION
-#define TARGET_VERSION fputs (" (ARM/ELF RTEMS)", stderr);
-
-#define HAS_INIT_SECTION
-
-#define TARGET_OS_CPP_BUILTINS() \
- do { \
- builtin_define ("__rtems__"); \
- builtin_assert ("system=rtems"); \
- } while (0)
-
-/*
- * The default in gcc now is soft-float, but gcc misses it to
- * pass it to the assembler.
- */
-#undef SUBTARGET_EXTRA_ASM_SPEC
-#define SUBTARGET_EXTRA_ASM_SPEC "\
- %{!mhard-float: %{!msoft-float:-mfpu=softfpa}}"
-
-/*
- * The default includes --start-group and --end-group which conflicts
- * with how this used to be defined.
- */
-#undef LINK_GCC_C_SEQUENCE_SPEC
-#define LINK_GCC_C_SEQUENCE_SPEC "%G %L"
diff --git a/gcc-4.2.1/gcc/config/arm/semi.h b/gcc-4.2.1/gcc/config/arm/semi.h
deleted file mode 100644
index 0de57d67a..000000000
--- a/gcc-4.2.1/gcc/config/arm/semi.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/* Definitions of target machine for GNU compiler. ARM on semi-hosted platform
- Copyright (C) 1994, 1995, 1996, 1997, 2001, 2004, 2005
- Free Software Foundation, Inc.
- Contributed by Richard Earnshaw (richard.earnshaw@arm.com)
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-#define STARTFILE_SPEC "crt0.o%s"
-
-#ifndef LIB_SPEC
-#define LIB_SPEC "-lc"
-#endif
-
-#ifndef SUBTARGET_CPP_SPEC
-#define SUBTARGET_CPP_SPEC "-D__semi__"
-#endif
-
-#ifndef LINK_SPEC
-#define LINK_SPEC "%{mbig-endian:-EB} -X"
-#endif
-
-#ifndef TARGET_VERSION
-#define TARGET_VERSION fputs (" (ARM/semi-hosted)", stderr);
-#endif
-
-#ifndef TARGET_DEFAULT_FLOAT_ABI
-#define TARGET_DEFAULT_FLOAT_ABI ARM_FLOAT_ABI_HARD
-#endif
-
-#ifndef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_APCS_FRAME)
-#endif
-
-#ifndef SUBTARGET_EXTRA_SPECS
-#define SUBTARGET_EXTRA_SPECS \
- { "subtarget_extra_asm_spec", SUBTARGET_EXTRA_ASM_SPEC },
-#endif
-
-#ifndef SUBTARGET_EXTRA_ASM_SPEC
-#define SUBTARGET_EXTRA_ASM_SPEC ""
-#endif
-
-/* The compiler supports PIC code generation, even though the binutils
- may not. If we are asked to compile position independent code, we
- always pass -k to the assembler. If it doesn't recognize it, then
- it will barf, which probably means that it doesn't know how to
- assemble PIC code. This is what we want, since otherwise tools
- may incorrectly assume we support PIC compilation even if the
- binutils can't. */
-#ifndef ASM_SPEC
-#define ASM_SPEC "\
-%{fpic|fpie: -k} %{fPIC|fPIE: -k} \
-%{mbig-endian:-EB} \
-%{mcpu=*:-mcpu=%*} \
-%{march=*:-march=%*} \
-%{mapcs-float:-mfloat} \
-%{msoft-float:-mfloat-abi=soft} %{mhard-float:-mfloat-abi=hard} \
-%{mfloat-abi=*} %{mfpu=*} \
-%{mthumb-interwork:-mthumb-interwork} \
-%(subtarget_extra_asm_spec)"
-#endif
diff --git a/gcc-4.2.1/gcc/config/arm/semiaof.h b/gcc-4.2.1/gcc/config/arm/semiaof.h
deleted file mode 100644
index 9038f0ddd..000000000
--- a/gcc-4.2.1/gcc/config/arm/semiaof.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* Definitions of target machine for GNU compiler. ARM on semi-hosted platform
- AOF Syntax assembler.
- Copyright (C) 1995, 1996, 1997, 2004 Free Software Foundation, Inc.
- Contributed by Richard Earnshaw (richard.earnshaw@armltd.co.uk)
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-#define TARGET_OS_CPP_BUILTINS() \
- do { \
- builtin_define_std ("arm"); \
- builtin_define_std ("semi"); \
- } while (0)
-
-#define ASM_SPEC "%{g -g} -arch 4 -apcs 3/32bit"
-
-#define LIB_SPEC "%{Eb: armlib_h.32b%s}%{!Eb: armlib_h.32l%s}"
-
-#define TARGET_VERSION fputs (" (ARM/semi-hosted)", stderr);
-
-#define TARGET_DEFAULT_FLOAT_ABI ARM_FLOAT_ABI_HARD
-
-#define TARGET_DEFAULT (0)
-
-/* The Norcroft C library defines size_t as "unsigned int". */
-#define SIZE_TYPE "unsigned int"
diff --git a/gcc-4.2.1/gcc/config/arm/strongarm-coff.h b/gcc-4.2.1/gcc/config/arm/strongarm-coff.h
deleted file mode 100644
index 0ba32ceaa..000000000
--- a/gcc-4.2.1/gcc/config/arm/strongarm-coff.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Definitions for StrongARM systems using COFF
- Copyright (C) 1999 Free Software Foundation, Inc.
- Contributed by Catherine Moore <clm@cygnus.com>
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* Run-time Target Specification. */
-#ifndef SUBTARGET_CPU_DEFAULT
-#define SUBTARGET_CPU_DEFAULT TARGET_CPU_strongarm
-#endif
-
-#undef TARGET_VERSION
-#define TARGET_VERSION fputs (" (StrongARM/COFF)", stderr);
diff --git a/gcc-4.2.1/gcc/config/arm/strongarm-elf.h b/gcc-4.2.1/gcc/config/arm/strongarm-elf.h
deleted file mode 100644
index 84c20996a..000000000
--- a/gcc-4.2.1/gcc/config/arm/strongarm-elf.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Definitions for non-Linux based StrongARM systems using ELF
- Copyright (C) 1999, 2001 Free Software Foundation, Inc.
- Contributed by Catherine Moore <clm@cygnus.com>
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* Run-time Target Specification. */
-#ifndef TARGET_VERSION
-#define TARGET_VERSION fputs (" (StrongARM/ELF non-Linux)", stderr);
-#endif
-
-#ifndef SUBTARGET_CPU_DEFAULT
-#define SUBTARGET_CPU_DEFAULT TARGET_CPU_strongarm
-#endif
-
diff --git a/gcc-4.2.1/gcc/config/arm/strongarm-pe.h b/gcc-4.2.1/gcc/config/arm/strongarm-pe.h
deleted file mode 100644
index f1a13c0dd..000000000
--- a/gcc-4.2.1/gcc/config/arm/strongarm-pe.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Definitions of target machine for GNU compiler, for ARM with PE obj format.
- Copyright (C) 1999 Free Software Foundation, Inc.
- Contributed by Doug Evans (dje@cygnus.com).
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-#undef TARGET_VERSION
-#define TARGET_VERSION fputs (" (StrongARM/PE)", stderr);
diff --git a/gcc-4.2.1/gcc/config/arm/symbian.h b/gcc-4.2.1/gcc/config/arm/symbian.h
deleted file mode 100644
index af1ba9a64..000000000
--- a/gcc-4.2.1/gcc/config/arm/symbian.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* Configuration file for Symbian OS on ARM processors.
- Copyright (C) 2004, 2005
- Free Software Foundation, Inc.
- Contributed by CodeSourcery, LLC
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* Do not expand builtin functions (unless explicitly prefixed with
- "__builtin"). Symbian OS code relies on properties of the standard
- library that go beyond those guaranteed by the ANSI/ISO standard.
- For example, "memcpy" works even with overlapping memory, like
- "memmove". We cannot simply set flag_no_builtin in arm.c because
- (a) flag_no_builtin is not declared in language-independent code,
- and (b) that would prevent users from explicitly overriding the
- default with -fbuiltin, which may sometimes be useful.
-
- Make all symbols hidden by default. Symbian OS expects that all
- exported symbols will be explicitly marked with
- "__declspec(dllexport)".
-
- Enumeration types use 4 bytes, even if the enumerals are small,
- unless explicitly overridden.
-
- The wchar_t type is a 2-byte type, unless explicitly
- overridden. */
-#define CC1_SPEC \
- "%{!fbuiltin:%{!fno-builtin:-fno-builtin}} " \
- "%{!fvisibility=*:-fvisibility=hidden} " \
- "%{!fshort-enums:%{!fno-short-enums:-fno-short-enums}} " \
- "%{!fshort-wchar:%{!fno-short-wchar:-fshort-wchar}} "
-#define CC1PLUS_SPEC CC1_SPEC
-
-/* Symbian OS does not use crt*.o, unlike the generic unknown-elf
- configuration. */
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC ""
-
-#undef ENDFILE_SPEC
-#define ENDFILE_SPEC ""
-
-/* Do not link with any libraries by default. On Symbian OS, the user
- must supply all required libraries on the command line. */
-#undef LIB_SPEC
-#define LIB_SPEC ""
-
-/* Support the "dllimport" attribute. */
-#define TARGET_DLLIMPORT_DECL_ATTRIBUTES 1
-
-/* Symbian OS assumes ARM V5 or above. Since -march=armv5 is
- equivalent to making the ARM 10TDMI core the default, we can set
- SUBTARGET_CPU_DEFAULT and get an equivalent effect. */
-#undef SUBTARGET_CPU_DEFAULT
-#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm10tdmi
-
-/* The assembler should assume VFP FPU format, and armv5t. */
-#undef SUBTARGET_ASM_FLOAT_SPEC
-#define SUBTARGET_ASM_FLOAT_SPEC \
- "%{!mfpu=*:-mfpu=vfp} %{!mcpu=*:%{!march=*:-march=armv5t}}"
-
-/* SymbianOS provides the BPABI routines in a separate library.
- Therefore, we do not need to define any of them in libgcc. */
-#undef RENAME_LIBRARY
-#define RENAME_LIBRARY(GCC_NAME, AEABI_NAME) /* empty */
-
-/* Define the __symbian__ macro. */
-#undef TARGET_OS_CPP_BUILTINS
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- /* Include the default BPABI stuff. */ \
- TARGET_BPABI_CPP_BUILTINS (); \
- builtin_define ("__symbian__"); \
- } \
- while (false)
-
-/* On SymbianOS, these sections are not writable, so we use "a",
- rather than "aw", for the section attributes. */
-#undef ARM_EABI_CTORS_SECTION_OP
-#define ARM_EABI_CTORS_SECTION_OP \
- "\t.section\t.init_array,\"a\",%init_array"
-#undef ARM_EABI_DTORS_SECTION_OP
-#define ARM_EABI_DTORS_SECTION_OP \
- "\t.section\t.fini_array,\"a\",%fini_array"
-
-/* SymbianOS cannot merge entities with vague linkage at runtime. */
-#define TARGET_ARM_DYNAMIC_VAGUE_LINKAGE_P false
diff --git a/gcc-4.2.1/gcc/config/arm/t-arm b/gcc-4.2.1/gcc/config/arm/t-arm
deleted file mode 100644
index 9fcd18786..000000000
--- a/gcc-4.2.1/gcc/config/arm/t-arm
+++ /dev/null
@@ -1,22 +0,0 @@
-# Rules common to all arm targets
-
-MD_INCLUDES= $(srcdir)/config/arm/arm-tune.md \
- $(srcdir)/config/arm/predicates.md \
- $(srcdir)/config/arm/arm-generic.md \
- $(srcdir)/config/arm/arm1020e.md \
- $(srcdir)/config/arm/arm1026ejs.md \
- $(srcdir)/config/arm/arm1136jfs.md \
- $(srcdir)/config/arm/arm926ejs.md \
- $(srcdir)/config/arm/cirrus.md \
- $(srcdir)/config/arm/fpa.md \
- $(srcdir)/config/arm/iwmmxt.md \
- $(srcdir)/config/arm/vfp.md
-
-s-config s-conditions s-flags s-codes s-constants s-emit s-recog s-preds \
- s-opinit s-extract s-peep s-attr s-attrtab s-output: $(MD_INCLUDES)
-
-$(srcdir)/config/arm/arm-tune.md: $(srcdir)/config/arm/gentune.sh \
- $(srcdir)/config/arm/arm-cores.def
- $(SHELL) $(srcdir)/config/arm/gentune.sh \
- $(srcdir)/config/arm/arm-cores.def > \
- $(srcdir)/config/arm/arm-tune.md
diff --git a/gcc-4.2.1/gcc/config/arm/t-arm-coff b/gcc-4.2.1/gcc/config/arm/t-arm-coff
deleted file mode 100644
index 0281cfd01..000000000
--- a/gcc-4.2.1/gcc/config/arm/t-arm-coff
+++ /dev/null
@@ -1,35 +0,0 @@
-LIB1ASMSRC = arm/lib1funcs.asm
-LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func _call_via_rX \
- _interwork_call_via_rX _muldi3
-
-# We want fine grained libraries, so use the new code to build the
-# floating point emulation libraries.
-FPBIT = fp-bit.c
-DPBIT = 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
-
-MULTILIB_OPTIONS = mlittle-endian/mbig-endian mhard-float/msoft-float marm/mthumb mno-thumb-interwork/mthumb-interwork
-MULTILIB_DIRNAMES = le be fpu soft arm thumb normal interwork
-MULTILIB_MATCHES =
-EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-
-# Currently there is a bug somewhere in GCC's alias analysis
-# or scheduling code that is breaking _fpmul_parts in fp-bit.c.
-# Disabling function inlining is a workaround for this problem.
-TARGET_LIBGCC2_CFLAGS = -fno-inline
diff --git a/gcc-4.2.1/gcc/config/arm/t-arm-elf b/gcc-4.2.1/gcc/config/arm/t-arm-elf
deleted file mode 100644
index 8994da094..000000000
--- a/gcc-4.2.1/gcc/config/arm/t-arm-elf
+++ /dev/null
@@ -1,116 +0,0 @@
-LIB1ASMSRC = arm/lib1funcs.asm
-LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func \
- _call_via_rX _interwork_call_via_rX \
- _lshrdi3 _ashrdi3 _ashldi3 \
- _negdf2 _addsubdf3 _muldivdf3 _cmpdf2 _unorddf2 _fixdfsi _fixunsdfsi \
- _truncdfsf2 _negsf2 _addsubsf3 _muldivsf3 _cmpsf2 _unordsf2 \
- _fixsfsi _fixunssfsi _floatdidf _floatdisf _floatundidf _floatundisf _muldi3
-
-# These functions are present in both lib1funcs.asm and arm-libgcc2.c. Only
-# one version of a function is built based on compilation time arch setting.
-LIB2FUNCS_EXTRA += $(srcdir)/config/arm/arm-libgcc2.c
-LIB2FUNCS_EXCLUDE += _clzdi2 _clzsi2
-LIB1ASMFUNCS += _clzdi2 _clzsi2
-
-MULTILIB_OPTIONS = marm/mthumb
-MULTILIB_DIRNAMES = arm thumb
-MULTILIB_EXCEPTIONS =
-MULTILIB_MATCHES =
-
-# MULTILIB_OPTIONS += mcpu=ep9312
-# MULTILIB_DIRNAMES += ep9312
-# MULTILIB_EXCEPTIONS += *mthumb/*mcpu=ep9312*
-#
-# MULTILIB_OPTIONS += mlittle-endian/mbig-endian
-# MULTILIB_DIRNAMES += le be
-# MULTILIB_MATCHES += mbig-endian=mbe mlittle-endian=mle
-#
-# MULTILIB_OPTIONS += mhard-float/msoft-float
-# MULTILIB_DIRNAMES += fpu soft
-# MULTILIB_EXCEPTIONS += *mthumb/*mhard-float*
-
-MULTILIB_OPTIONS += mno-thumb-interwork/mthumb-interwork
-MULTILIB_DIRNAMES += normal interwork
-
-# -mandroind implies -mthumb-interwork
-MULTILIB_OPTIONS += mandroid
-MULTILIB_DIRNAMES += android
-MULTILIB_EXCEPTIONS += *mthumb-interwork/*mandroid*
-
-# MULTILIB_OPTIONS += fno-leading-underscore/fleading-underscore
-# MULTILIB_DIRNAMES += elf under
-#
-# MULTILIB_OPTIONS += mcpu=arm7
-# MULTILIB_DIRNAMES += nofmult
-# MULTILIB_EXCEPTIONS += *mthumb*/*mcpu=arm7*
-# # Note: the multilib_exceptions matches both -mthumb and
-# # -mthumb-interwork
-# #
-# # We have to match all the arm cpu variants which do not have the
-# # multiply instruction and treat them as if the user had specified
-# # -mcpu=arm7. Note that in the following the ? is interpreted as
-# # an = for the purposes of matching command line options.
-# # FIXME: There ought to be a better way to do this.
-# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm7d
-# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm7di
-# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm70
-# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm700
-# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm700i
-# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm710
-# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm710c
-# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm7100
-# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm7500
-# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm7500fe
-# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm6
-# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm60
-# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm600
-# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm610
-# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm620
-
-EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
-
-# If EXTRA_MULTILIB_PARTS is not defined above then define EXTRA_PARTS here
-# EXTRA_PARTS = crtbegin.o crtend.o crti.o crtn.o
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-
-# Currently there is a bug somewhere in GCC's alias analysis
-# or scheduling code that is breaking _fpmul_parts in fp-bit.c.
-# Disabling function inlining is a workaround for this problem.
-TARGET_LIBGCC2_CFLAGS = -fno-inline
-
-# Assemble startup files.
-$(T)crti.o: $(srcdir)/config/arm/crti.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/arm/crti.asm
-
-$(T)crtn.o: $(srcdir)/config/arm/crtn.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/arm/crtn.asm
-
-# ANDROID LOCAL BEGIN
-# Build a shared libgcc library.
-# Only work for Android
-SHLIB_EXT = .so
-SHLIB_NAME = @shlib_base_name@.so
-SHLIB_SONAME = @shlib_base_name@.so.1
-SHLIB_OBJS = @shlib_objs@
-
-SHLIB_LINK = $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
- -Wl,-soname,$(SHLIB_SONAME) \
- -o $(SHLIB_NAME).tmp @multilib_flags@ $(SHLIB_OBJS) -lc && \
- rm -f $(SHLIB_SONAME) && \
- if [ -f $(SHLIB_NAME) ]; then \
- mv -f $(SHLIB_NAME) $(SHLIB_NAME).backup; \
- else true; fi && \
- mv $(SHLIB_NAME).tmp $(SHLIB_NAME) && \
- $(LN_S) $(SHLIB_NAME) $(SHLIB_SONAME)
-# $(slibdir) double quoted to protect it from expansion while building
-# libgcc.mk. We want this delayed until actual install time.
-SHLIB_INSTALL = \
- $$(mkinstalldirs) $$(DESTDIR)$$(slibdir); \
- $(INSTALL_DATA) $(SHLIB_NAME) $$(DESTDIR)$$(slibdir)/$(SHLIB_SONAME); \
- rm -f $$(DESTDIR)$$(slibdir)/$(SHLIB_NAME); \
- $(LN_S) $(SHLIB_SONAME) $$(DESTDIR)$$(slibdir)/$(SHLIB_NAME)
-# ANDROID LOCAL END
diff --git a/gcc-4.2.1/gcc/config/arm/t-bpabi b/gcc-4.2.1/gcc/config/arm/t-bpabi
deleted file mode 100644
index fc40c2db8..000000000
--- a/gcc-4.2.1/gcc/config/arm/t-bpabi
+++ /dev/null
@@ -1,22 +0,0 @@
-# Add the bpabi.S functions.
-LIB1ASMFUNCS += _aeabi_lcmp _aeabi_ulcmp _aeabi_ldivmod _aeabi_uldivmod
-
-# Add the BPABI C functions.
-LIB2FUNCS_EXTRA = $(srcdir)/config/arm/bpabi.c \
- $(srcdir)/config/arm/unaligned-funcs.c
-
-# These functions are present in both lib1funcs.asm and arm-libgcc2.c. Only
-# one version of a function is built based on compilation time arch setting.
-LIB2FUNCS_EXTRA += $(srcdir)/config/arm/arm-libgcc2.c
-LIB2FUNCS_EXCLUDE += _clzdi2 _clzsi2
-LIB1ASMFUNCS += _clzdi2 _clzsi2
-
-UNWIND_H = $(srcdir)/config/arm/unwind-arm.h
-LIB2ADDEH = $(srcdir)/config/arm/unwind-arm.c \
- $(srcdir)/config/arm/libunwind.S \
- $(srcdir)/config/arm/pr-support.c $(srcdir)/unwind-c.c
-LIB2ADDEHDEP = $(UNWIND_H) $(srcdir)/config/$(LIB1ASMSRC)
-
-# Add the BPABI names.
-SHLIB_MAPFILES += $(srcdir)/config/arm/libgcc-bpabi.ver
-
diff --git a/gcc-4.2.1/gcc/config/arm/t-linux b/gcc-4.2.1/gcc/config/arm/t-linux
deleted file mode 100644
index 47d61d693..000000000
--- a/gcc-4.2.1/gcc/config/arm/t-linux
+++ /dev/null
@@ -1,21 +0,0 @@
-# Just for these, we omit the frame pointer since it makes such a big
-# difference. It is then pointless adding debugging.
-TARGET_LIBGCC2_CFLAGS = -fomit-frame-pointer -fPIC
-LIBGCC2_DEBUG_CFLAGS = -g0
-
-LIB1ASMSRC = arm/lib1funcs.asm
-LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_lnx _muldi3
-
-# These functions are present in both lib1funcs.asm and arm-libgcc2.c. Only
-# one version of a function is built based on compilation time arch setting.
-LIB2FUNCS_EXTRA += $(srcdir)/config/arm/arm-libgcc2.c
-LIB2FUNCS_EXCLUDE += _clzdi2 _clzsi2
-LIB1ASMFUNCS += _clzdi2 _clzsi2
-
-# MULTILIB_OPTIONS = mhard-float/msoft-float
-# MULTILIB_DIRNAMES = hard-float soft-float
-
-# EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o
-
-# LIBGCC = stmp-multilib
-# INSTALL_LIBGCC = install-multilib
diff --git a/gcc-4.2.1/gcc/config/arm/t-linux-eabi b/gcc-4.2.1/gcc/config/arm/t-linux-eabi
deleted file mode 100644
index 19c5c0681..000000000
--- a/gcc-4.2.1/gcc/config/arm/t-linux-eabi
+++ /dev/null
@@ -1,20 +0,0 @@
-# These functions are included in shared libraries.
-TARGET_LIBGCC2_CFLAGS = -fPIC
-
-# We do not build a Thumb multilib for Linux because the definition of
-# CLEAR_INSN_CACHE in linux-gas.h does not work in Thumb mode.
-MULTILIB_OPTIONS =
-MULTILIB_DIRNAMES =
-
-# Use a version of div0 which raises SIGFPE.
-LIB1ASMFUNCS := $(filter-out _dvmd_tls,$(LIB1ASMFUNCS)) _dvmd_lnx
-
-# These functions are present in both lib1funcs.asm and arm-libgcc2.c. Only
-# one version of a function is built based on compilation time arch setting.
-LIB2FUNCS_EXTRA += $(srcdir)/config/arm/arm-libgcc2.c
-LIB2FUNCS_EXCLUDE += _clzdi2 _clzsi2
-LIB1ASMFUNCS += _clzdi2 _clzsi2
-
-# Multilib the standard Linux files. Don't include crti.o or crtn.o,
-# which are provided by glibc.
-EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o
diff --git a/gcc-4.2.1/gcc/config/arm/t-netbsd b/gcc-4.2.1/gcc/config/arm/t-netbsd
deleted file mode 100644
index 7d0724cc8..000000000
--- a/gcc-4.2.1/gcc/config/arm/t-netbsd
+++ /dev/null
@@ -1,28 +0,0 @@
-# Just for these, we omit the frame pointer since it makes such a big
-# difference. It is then pointless adding debugging.
-TARGET_LIBGCC2_CFLAGS = -fomit-frame-pointer -fpic
-LIBGCC2_DEBUG_CFLAGS = -g0
-LIB2FUNCS_EXTRA = $(srcdir)/config/floatunsidf.c $(srcdir)/config/floatunsisf.c
-
-# Build a shared libgcc library.
-SHLIB_EXT = .so
-SHLIB_NAME = @shlib_base_name@.so
-SHLIB_SONAME = @shlib_base_name@.so.1
-SHLIB_OBJS = @shlib_objs@
-
-SHLIB_LINK = $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
- -Wl,-soname,$(SHLIB_SONAME) \
- -o $(SHLIB_NAME).tmp @multilib_flags@ $(SHLIB_OBJS) -lc && \
- rm -f $(SHLIB_SONAME) && \
- if [ -f $(SHLIB_NAME) ]; then \
- mv -f $(SHLIB_NAME) $(SHLIB_NAME).backup; \
- else true; fi && \
- mv $(SHLIB_NAME).tmp $(SHLIB_NAME) && \
- $(LN_S) $(SHLIB_NAME) $(SHLIB_SONAME)
-# $(slibdir) double quoted to protect it from expansion while building
-# libgcc.mk. We want this delayed until actual install time.
-SHLIB_INSTALL = \
- $$(mkinstalldirs) $$(DESTDIR)$$(slibdir); \
- $(INSTALL_DATA) $(SHLIB_NAME) $$(DESTDIR)$$(slibdir)/$(SHLIB_SONAME); \
- rm -f $$(DESTDIR)$$(slibdir)/$(SHLIB_NAME); \
- $(LN_S) $(SHLIB_SONAME) $$(DESTDIR)$$(slibdir)/$(SHLIB_NAME)
diff --git a/gcc-4.2.1/gcc/config/arm/t-pe b/gcc-4.2.1/gcc/config/arm/t-pe
deleted file mode 100644
index f2b2f9197..000000000
--- a/gcc-4.2.1/gcc/config/arm/t-pe
+++ /dev/null
@@ -1,33 +0,0 @@
-LIB1ASMSRC = arm/lib1funcs.asm
-LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _call_via_rX \
- _interwork_call_via_rX _muldi3
-
-# We want fine grained libraries, so use the new code to build the
-# floating point emulation libraries.
-FPBIT = fp-bit.c
-DPBIT = 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
-
-pe.o: $(srcdir)/config/arm/pe.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) output.h flags.h $(TREE_H) expr.h toplev.h $(TM_P_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/arm/pe.c
-
-MULTILIB_OPTIONS = mhard-float mthumb
-MULTILIB_DIRNAMES = fpu thumb
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-TARGET_LIBGCC2_CFLAGS =
diff --git a/gcc-4.2.1/gcc/config/arm/t-rtems b/gcc-4.2.1/gcc/config/arm/t-rtems
deleted file mode 100644
index 52d14bab0..000000000
--- a/gcc-4.2.1/gcc/config/arm/t-rtems
+++ /dev/null
@@ -1,10 +0,0 @@
-# Custom rtems multilibs
-
-MULTILIB_OPTIONS = marm/mthumb
-MULTILIB_DIRNAMES = arm thumb
-MULTILIB_EXCEPTIONS =
-MULTILIB_MATCHES = marm=mno-thumb
-
-MULTILIB_OPTIONS += msoft-float/mhard-float
-MULTILIB_DIRNAMES += soft fpu
-MULTILIB_EXCEPTIONS += *mthumb/*mhard-float*
diff --git a/gcc-4.2.1/gcc/config/arm/t-semi b/gcc-4.2.1/gcc/config/arm/t-semi
deleted file mode 100644
index b4eb2a3a3..000000000
--- a/gcc-4.2.1/gcc/config/arm/t-semi
+++ /dev/null
@@ -1,38 +0,0 @@
-# Just for these, we omit the frame pointer since it makes such a big
-# difference. It is then pointless adding debugging.
-TARGET_LIBGCC2_CFLAGS = -fomit-frame-pointer
-LIBGCC2_DEBUG_CFLAGS = -g0
-
-LIB1ASMSRC = arm/lib1funcs.asm
-LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _call_via_rX \
- _interwork_call_via_rX _muldi3
-
-# We want fine grained libraries, so use the new code to build the
-# floating point emulation libraries.
-FPBIT = fp-bit.c
-DPBIT = dp-bit.c
-
-fp-bit.c: $(srcdir)/config/fp-bit.c
- echo '#ifdef __SOFTFP__' > 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
- echo '#endif' >> fp-bit.c
-
-dp-bit.c: $(srcdir)/config/fp-bit.c
- echo '#ifdef __SOFTFP__' > dp-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
- echo '#endif' >> dp-bit.c
-
-MULTILIB_OPTIONS = msoft-float mbig-endian mwords-little-endian
-MULTILIB_DIRNAMES = soft big wlittle
-MULTILIB_EXCEPTIONS = mwords-little-endian msoft-float/mwords-little-endian
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
diff --git a/gcc-4.2.1/gcc/config/arm/t-strongarm-elf b/gcc-4.2.1/gcc/config/arm/t-strongarm-elf
deleted file mode 100644
index 23f748bab..000000000
--- a/gcc-4.2.1/gcc/config/arm/t-strongarm-elf
+++ /dev/null
@@ -1,44 +0,0 @@
-LIB1ASMSRC = arm/lib1funcs.asm
-LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func _muldi3
-
-# We want fine grained libraries, so use the new code to build the
-# floating point emulation libraries.
-FPBIT = fp-bit.c
-DPBIT = 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
-
-MULTILIB_OPTIONS = mlittle-endian/mbig-endian mhard-float/msoft-float
-MULTILIB_DIRNAMES = le be fpu soft
-MULTILIB_EXCEPTIONS =
-MULTILIB_MATCHES = mbig-endian=mbe mlittle-endian=mle
-EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-
-# Currently there is a bug somewhere in GCC's alias analysis
-# or scheduling code that is breaking _fpmul_parts in fp-bit.c.
-# Disabling function inlining is a workaround for this problem.
-TARGET_LIBGCC2_CFLAGS = -fno-inline
-
-# Assemble startup files.
-$(T)crti.o: $(srcdir)/config/arm/crti.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/arm/crti.asm
-
-$(T)crtn.o: $(srcdir)/config/arm/crtn.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/arm/crtn.asm
diff --git a/gcc-4.2.1/gcc/config/arm/t-strongarm-pe b/gcc-4.2.1/gcc/config/arm/t-strongarm-pe
deleted file mode 100644
index 278cfdfc5..000000000
--- a/gcc-4.2.1/gcc/config/arm/t-strongarm-pe
+++ /dev/null
@@ -1,38 +0,0 @@
-LIB1ASMSRC = arm/lib1funcs.asm
-LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func _muldi3
-
-# We want fine grained libraries, so use the new code to build the
-# floating point emulation libraries.
-FPBIT = fp-bit.c
-DPBIT = 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
-
-pe.o: $(srcdir)/config/arm/pe.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) output.h flags.h $(TREE_H) expr.h toplev.h $(TM_P_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/arm/pe.c
-
-MULTILIB_OPTIONS = mhard-float/msoft-float
-MULTILIB_DIRNAMES = fpu soft
-MULTILIB_MATCHES =
-EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-
-# Currently there is a bug somewhere in GCC's alias analysis
-# or scheduling code that is breaking _fpmul_parts in fp-bit.c.
-# Disabling function inlining is a workaround for this problem.
-TARGET_LIBGCC2_CFLAGS = -fno-inline
diff --git a/gcc-4.2.1/gcc/config/arm/t-symbian b/gcc-4.2.1/gcc/config/arm/t-symbian
deleted file mode 100644
index 9347e95e7..000000000
--- a/gcc-4.2.1/gcc/config/arm/t-symbian
+++ /dev/null
@@ -1,32 +0,0 @@
-LIB1ASMFUNCS = _bb_init_func _call_via_rX _interwork_call_via_rX
-
-# These functions have __aeabi equivalents and will never be called by GCC.
-# By putting them in LIB1ASMFUNCS, we avoid the standard libgcc2.c code being
-# used -- and we make sure that definitions are not available in lib1funcs.asm,
-# either, so they end up undefined.
-LIB1ASMFUNCS += \
- _ashldi3 _ashrdi3 _divdi3 _floatdidf _udivmoddi4 _umoddi3 \
- _udivdi3 _lshrdi3 _moddi3 _muldi3 _negdi2 _cmpdi2 \
- _fixdfdi _fixsfdi _fixunsdfdi _fixunssfdi _floatdisf \
- _negdf2 _addsubdf3 _muldivdf3 _cmpdf2 _unorddf2 _fixdfsi _fixunsdfsi \
- _truncdfsf2 _negsf2 _addsubsf3 _muldivsf3 _cmpsf2 _unordsf2 \
- _fixsfsi _fixunssfsi _muldi3
-
-# Include the gcc personality routine
-UNWIND_H = $(srcdir)/config/arm/unwind-arm.h
-LIB2ADDEH = $(srcdir)/unwind-c.c $(srcdir)/config/arm/pr-support.c
-LIB2ADDEHDEP = $(UNWIND_H)
-
-# Create a multilib for processors with VFP floating-point, and a
-# multilib for those without -- using the soft-float ABI in both
-# cases. Symbian OS object should be compiled with interworking
-# enabled, so there are no separate thumb-mode libraries.
-MULTILIB_OPTIONS = mfloat-abi=softfp
-MULTILIB_DIRNAMES = softfp
-
-# There is no C library to link against on Symbian OS -- at least when
-# building GCC.
-SHLIB_LC =
-
-# Symbian OS provides its own startup code.
-EXTRA_MULTILIB_PARTS=
diff --git a/gcc-4.2.1/gcc/config/arm/t-vxworks b/gcc-4.2.1/gcc/config/arm/t-vxworks
deleted file mode 100644
index e620cfdf8..000000000
--- a/gcc-4.2.1/gcc/config/arm/t-vxworks
+++ /dev/null
@@ -1,10 +0,0 @@
-# Multilibs for VxWorks.
-
-MULTILIB_OPTIONS = \
- t4/t4be/t4t/t4tbe/t5/t5be/t5t/t5tbe/txscale/txscalebe
-
-MULTILIB_DIRNAMES = \
- ARMARCH4gnu ARMARCH4gnube ARMARCH4_Tgnu ARMARCH4_Tgnube \
- ARMARCH5gnu ARMARCH5gnube ARMARCH5_Tgnu ARMARCH5_Tgnube \
- XSCALEgnu XSCALEgnube
-
diff --git a/gcc-4.2.1/gcc/config/arm/t-wince-pe b/gcc-4.2.1/gcc/config/arm/t-wince-pe
deleted file mode 100644
index daeea1fad..000000000
--- a/gcc-4.2.1/gcc/config/arm/t-wince-pe
+++ /dev/null
@@ -1,38 +0,0 @@
-LIB1ASMSRC = arm/lib1funcs.asm
-LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _call_via_rX \
- _interwork_call_via_rX _muldi3
-
-# We want fine grained libraries, so use the new code to build the
-# floating point emulation libraries.
-FPBIT = fp-bit.c
-DPBIT = 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
-
-pe.o: $(srcdir)/config/arm/pe.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) output.h flags.h $(TREE_H) expr.h toplev.h $(TM_P_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/arm/pe.c
-
-MULTILIB_OPTIONS = mhard-float
-MULTILIB_DIRNAMES = fpu
-# Note - Thumb multilib omitted because Thumb support for
-# arm-wince-pe target does not appear to be working in binutils
-# yet...
-# MULTILIB_OPTIONS += thumb
-# MULTILIB_DIRNAMES += thumb
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-TARGET_LIBGCC2_CFLAGS =
diff --git a/gcc-4.2.1/gcc/config/arm/t-xscale-coff b/gcc-4.2.1/gcc/config/arm/t-xscale-coff
deleted file mode 100644
index d288d694f..000000000
--- a/gcc-4.2.1/gcc/config/arm/t-xscale-coff
+++ /dev/null
@@ -1,46 +0,0 @@
-LIB1ASMSRC = arm/lib1funcs.asm
-LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func \
- _call_via_rX _interwork_call_via_rX _muldi3
-
-# We want fine grained libraries, so use the new code to build the
-# floating point emulation libraries.
-FPBIT = fp-bit.c
-DPBIT = 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
-
-MULTILIB_OPTIONS = mbig-endian
-MULTILIB_DIRNAMES = be
-MULTILIB_EXCEPTIONS =
-MULTILIB_MATCHES = mbig-endian=mbe mlittle-endian=mle
-
-# Note XScale does not support hard FP
-
-MULTILIB_OPTIONS += mthumb-interwork
-MULTILIB_DIRNAMES += interwork
-
-MULTILIB_OPTIONS += mthumb
-MULTILIB_DIRNAMES += thumb
-MULTILIB_EXCEPTIONS += *mhard-float/*mthumb*
-
-MULTILIB_REDUNDANT_DIRS = interwork/thumb=thumb
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-
-# Currently there is a bug somewhere in GCC's alias analysis
-# or scheduling code that is breaking _fpmul_parts in fp-bit.c.
-# Disabling function inlining is a workaround for this problem.
-TARGET_LIBGCC2_CFLAGS = -fno-inline
diff --git a/gcc-4.2.1/gcc/config/arm/t-xscale-elf b/gcc-4.2.1/gcc/config/arm/t-xscale-elf
deleted file mode 100644
index 7b6cdbad9..000000000
--- a/gcc-4.2.1/gcc/config/arm/t-xscale-elf
+++ /dev/null
@@ -1,67 +0,0 @@
-LIB1ASMSRC = arm/lib1funcs.asm
-LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func _call_via_rX \
- _interwork_call_via_rX muldi3
-
-# We want fine grained libraries, so use the new code to build the
-# floating point emulation libraries.
-FPBIT = fp-bit.c
-DPBIT = 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
-
-MULTILIB_OPTIONS = mbig-endian
-MULTILIB_DIRNAMES = be
-MULTILIB_EXCEPTIONS =
-MULTILIB_MATCHES = mbig-endian=mbe mlittle-endian=mle
-
-# Note XScale does not support hard FP
-
-MULTILIB_OPTIONS += mthumb-interwork
-MULTILIB_DIRNAMES += interwork
-
-MULTILIB_OPTIONS += mthumb
-MULTILIB_DIRNAMES += thumb
-MULTILIB_EXCEPTIONS += *mhard-float/*mthumb*
-
-MULTILIB_REDUNDANT_DIRS = interwork/thumb=thumb
-
-# The iWMMXt multilibs are suppressed for now because gcc only
-# supports generating them with the IWMMXT or AAPCS ABIs, neither of
-# which is the default. Until GCC can generate code for an iWMMXt
-# which will work with the default ABI it is not possible to safely
-# generate these multilibs.
-#
-# MULTILIB_OPTIONS += mcpu=iwmmxt
-# MULTILIB_DIRNAMES += iwmmxt
-# MULTILIB_REDUNDANT_DIRS += interwork/thumb/iwmmxt=thumb
-
-EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-
-# Currently there is a bug somewhere in GCC's alias analysis
-# or scheduling code that is breaking _fpmul_parts in fp-bit.c.
-# Disabling function inlining is a workaround for this problem.
-TARGET_LIBGCC2_CFLAGS = -fno-inline
-
-# Assemble startup files.
-$(T)crti.o: $(srcdir)/config/arm/crti.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/arm/crti.asm
-
-$(T)crtn.o: $(srcdir)/config/arm/crtn.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/arm/crtn.asm
diff --git a/gcc-4.2.1/gcc/config/arm/uclinux-elf.h b/gcc-4.2.1/gcc/config/arm/uclinux-elf.h
deleted file mode 100644
index 9f112cdda..000000000
--- a/gcc-4.2.1/gcc/config/arm/uclinux-elf.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/* Definitions for ARM running ucLinux using ELF
- Copyright (C) 1999, 2001, 2004, 2005 Free Software Foundation, Inc.
- Contributed by Philip Blundell <pb@nexus.co.uk>
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* We don't want a PLT. */
-#undef NEED_PLT_RELOC
-#define NEED_PLT_RELOC 0
-
-#undef TARGET_VERSION
-#define TARGET_VERSION fputs (" (ARM/ELF ucLinux)", stderr);
-
-#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_SINGLE_PIC_BASE)
-
-/* NOTE: The remaining definitions in this file are needed because uclinux
- does not use config/linux.h. */
-
-/* Do not assume anything about header files. */
-#define NO_IMPLICIT_EXTERN_C
-
-/* The GNU C++ standard library requires that these macros be defined. */
-#undef CPLUSPLUS_CPP_SPEC
-#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
-
-/* Provide a STARTFILE_SPEC appropriate for GNU/Linux. Here we add
- the GNU/Linux magical crtbegin.o file (see crtstuff.c) which
- provides part of the support for getting C++ file-scope static
- object constructed before entering `main'. */
-
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC \
- "%{!shared: \
- %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} \
- %{!p:%{profile:gcrt1.o%s} \
- %{!profile:crt1.o%s}}}} \
- crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}"
-
-/* Provide a ENDFILE_SPEC appropriate for GNU/Linux. Here we tack on
- the GNU/Linux magical crtend.o file (see crtstuff.c) which
- provides part of the support for getting C++ file-scope static
- object constructed before entering `main', followed by a normal
- GNU/Linux "finalizer" file, `crtn.o'. */
-
-#undef ENDFILE_SPEC
-#define ENDFILE_SPEC \
- "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s"
-
-#undef CC1_SPEC
-#define CC1_SPEC "%{profile:-p}"
-
-#define LINK_GCC_C_SEQUENCE_SPEC \
- "%{static:--start-group} %G %L %{static:--end-group}%{!static:%G}"
-
-/* Use --as-needed -lgcc_s for eh support. */
-#ifdef HAVE_LD_AS_NEEDED
-#define USE_LD_AS_NEEDED 1
-#endif
diff --git a/gcc-4.2.1/gcc/config/arm/unaligned-funcs.c b/gcc-4.2.1/gcc/config/arm/unaligned-funcs.c
deleted file mode 100644
index 66cfd3bbb..000000000
--- a/gcc-4.2.1/gcc/config/arm/unaligned-funcs.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/* EABI unaligned read/write functions.
-
- Copyright (C) 2005 Free Software Foundation, Inc.
- Contributed by CodeSourcery, LLC.
-
- 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 into combinations with other programs,
- and to distribute those combinations 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 a combine
- executable.)
-
- 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, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-int __aeabi_uread4 (void *);
-int __aeabi_uwrite4 (int, void *);
-long long __aeabi_uread8 (void *);
-long long __aeabi_uwrite8 (long long, void *);
-
-struct __attribute__((packed)) u4 { int data; };
-struct __attribute__((packed)) u8 { long long data; };
-
-int
-__aeabi_uread4 (void *ptr)
-{
- return ((struct u4 *) ptr)->data;
-}
-
-int
-__aeabi_uwrite4 (int data, void *ptr)
-{
- ((struct u4 *) ptr)->data = data;
- return data;
-}
-
-long long
-__aeabi_uread8 (void *ptr)
-{
- return ((struct u8 *) ptr)->data;
-}
-
-long long
-__aeabi_uwrite8 (long long data, void *ptr)
-{
- ((struct u8 *) ptr)->data = data;
- return data;
-}
diff --git a/gcc-4.2.1/gcc/config/arm/unknown-elf.h b/gcc-4.2.1/gcc/config/arm/unknown-elf.h
deleted file mode 100644
index 26d5c17ea..000000000
--- a/gcc-4.2.1/gcc/config/arm/unknown-elf.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* Definitions for non-Linux based ARM systems using ELF
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
- Free Software Foundation, Inc.
- Contributed by Catherine Moore <clm@cygnus.com>
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* elfos.h should have already been included. Now just override
- any conflicting definitions and add any extras. */
-
-/* Run-time Target Specification. */
-#ifndef TARGET_VERSION
-#define TARGET_VERSION fputs (" (ARM/ELF)", stderr);
-#endif
-
-/* Default to using software floating point. */
-#ifndef TARGET_DEFAULT
-#define TARGET_DEFAULT (0)
-#endif
-
-/* Now we define the strings used to build the spec file. */
-#define UNKNOWN_ELF_STARTFILE_SPEC " crti%O%s crtbegin%O%s crt0%O%s"
-
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC UNKNOWN_ELF_STARTFILE_SPEC
-
-#define UNKNOWN_ELF_ENDFILE_SPEC "crtend%O%s crtn%O%s"
-
-#undef ENDFILE_SPEC
-#define ENDFILE_SPEC UNKNOWN_ELF_ENDFILE_SPEC
-
-/* The __USES_INITFINI__ define is tested in newlib/libc/sys/arm/crt0.S
- to see if it needs to invoked _init() and _fini(). */
-#undef SUBTARGET_CPP_SPEC
-#define SUBTARGET_CPP_SPEC "-D__USES_INITFINI__"
-
-#undef PREFERRED_DEBUGGING_TYPE
-#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
-
-/* Return a nonzero value if DECL has a section attribute. */
-#define IN_NAMED_SECTION(DECL) \
- ((TREE_CODE (DECL) == FUNCTION_DECL || TREE_CODE (DECL) == VAR_DECL) \
- && DECL_SECTION_NAME (DECL) != NULL_TREE)
-
-#undef ASM_OUTPUT_ALIGNED_BSS
-#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
- do \
- { \
- if (IN_NAMED_SECTION (DECL)) \
- switch_to_section (get_named_section (DECL, NULL, 0)); \
- else \
- switch_to_section (bss_section); \
- \
- ASM_OUTPUT_ALIGN (FILE, floor_log2 (ALIGN / BITS_PER_UNIT)); \
- \
- last_assemble_variable_decl = DECL; \
- ASM_DECLARE_OBJECT_NAME (FILE, NAME, DECL); \
- ASM_OUTPUT_SKIP (FILE, SIZE ? (int)(SIZE) : 1); \
- } \
- while (0)
-
-#undef ASM_OUTPUT_ALIGNED_DECL_LOCAL
-#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(FILE, DECL, NAME, SIZE, ALIGN) \
- do \
- { \
- if ((DECL) != NULL && IN_NAMED_SECTION (DECL)) \
- switch_to_section (get_named_section (DECL, NULL, 0)); \
- else \
- switch_to_section (bss_section); \
- \
- ASM_OUTPUT_ALIGN (FILE, floor_log2 (ALIGN / BITS_PER_UNIT)); \
- ASM_OUTPUT_LABEL (FILE, NAME); \
- fprintf (FILE, "\t.space\t%d\n", SIZE ? (int)(SIZE) : 1); \
- } \
- while (0)
-
-#ifndef SUBTARGET_CPU_DEFAULT
-#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm7tdmi
-#endif
-
-/* The libgcc udivmod functions may throw exceptions. If newlib is
- configured to support long longs in I/O, then printf will depend on
- udivmoddi4, which will depend on the exception unwind routines,
- which will depend on abort, which is defined in libc. */
-#undef LINK_GCC_C_SEQUENCE_SPEC
-#define LINK_GCC_C_SEQUENCE_SPEC "--start-group %G %L --end-group"
diff --git a/gcc-4.2.1/gcc/config/arm/unwind-arm.c b/gcc-4.2.1/gcc/config/arm/unwind-arm.c
deleted file mode 100644
index 41d89d104..000000000
--- a/gcc-4.2.1/gcc/config/arm/unwind-arm.c
+++ /dev/null
@@ -1,1076 +0,0 @@
-/* ARM EABI compliant unwinding routines.
- Copyright (C) 2004, 2005 Free Software Foundation, Inc.
- Contributed by Paul Brook
-
- 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 into combinations with other programs,
- and to distribute those combinations 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 a combine
- executable.)
-
- 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, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-#include "unwind.h"
-
-/* We add a prototype for abort here to avoid creating a dependency on
- target headers. */
-extern void abort (void);
-
-/* Definitions for C++ runtime support routines. We make these weak
- declarations to avoid pulling in libsupc++ unnecessarily. */
-typedef unsigned char bool;
-
-typedef struct _ZSt9type_info type_info; /* This names C++ type_info type */
-
-void __attribute__((weak)) __cxa_call_unexpected(_Unwind_Control_Block *ucbp);
-bool __attribute__((weak)) __cxa_begin_cleanup(_Unwind_Control_Block *ucbp);
-bool __attribute__((weak)) __cxa_type_match(_Unwind_Control_Block *ucbp,
- const type_info *rttip,
- void **matched_object);
-
-_Unwind_Ptr __attribute__((weak))
-__gnu_Unwind_Find_exidx (_Unwind_Ptr, int *);
-
-/* Misc constants. */
-#define R_IP 12
-#define R_SP 13
-#define R_LR 14
-#define R_PC 15
-
-#define EXIDX_CANTUNWIND 1
-#define uint32_highbit (((_uw) 1) << 31)
-
-#define UCB_FORCED_STOP_FN(ucbp) ((ucbp)->unwinder_cache.reserved1)
-#define UCB_PR_ADDR(ucbp) ((ucbp)->unwinder_cache.reserved2)
-#define UCB_SAVED_CALLSITE_ADDR(ucbp) ((ucbp)->unwinder_cache.reserved3)
-#define UCB_FORCED_STOP_ARG(ucbp) ((ucbp)->unwinder_cache.reserved4)
-
-struct core_regs
-{
- _uw r[16];
-};
-
-/* We use normal integer types here to avoid the compiler generating
- coprocessor instructions. */
-struct vfp_regs
-{
- _uw64 d[16];
- _uw pad;
-};
-
-struct fpa_reg
-{
- _uw w[3];
-};
-
-struct fpa_regs
-{
- struct fpa_reg f[8];
-};
-
-/* Unwind descriptors. */
-
-typedef struct
-{
- _uw16 length;
- _uw16 offset;
-} EHT16;
-
-typedef struct
-{
- _uw length;
- _uw offset;
-} EHT32;
-
-/* The ABI specifies that the unwind routines may only use core registers,
- except when actually manipulating coprocessor state. This allows
- us to write one implementation that works on all platforms by
- demand-saving coprocessor registers.
-
- During unwinding we hold the coprocessor state in the actual hardware
- registers and allocate demand-save areas for use during phase1
- unwinding. */
-
-typedef struct
-{
- /* The first fields must be the same as a phase2_vrs. */
- _uw demand_save_flags;
- struct core_regs core;
- _uw prev_sp; /* Only valid during forced unwinding. */
- struct vfp_regs vfp;
- struct fpa_regs fpa;
-} phase1_vrs;
-
-#define DEMAND_SAVE_VFP 1
-
-/* This must match the structure created by the assembly wrappers. */
-typedef struct
-{
- _uw demand_save_flags;
- struct core_regs core;
-} phase2_vrs;
-
-
-/* An exception index table entry. */
-
-typedef struct __EIT_entry
-{
- _uw fnoffset;
- _uw content;
-} __EIT_entry;
-
-/* Assembly helper functions. */
-
-/* Restore core register state. Never returns. */
-void __attribute__((noreturn)) restore_core_regs (struct core_regs *);
-
-
-/* Coprocessor register state manipulation functions. */
-
-void __gnu_Unwind_Save_VFP (struct vfp_regs * p);
-void __gnu_Unwind_Restore_VFP (struct vfp_regs * p);
-
-/* Restore coprocessor state after phase1 unwinding. */
-static void
-restore_non_core_regs (phase1_vrs * vrs)
-{
- if ((vrs->demand_save_flags & DEMAND_SAVE_VFP) == 0)
- __gnu_Unwind_Restore_VFP (&vrs->vfp);
-}
-
-/* A better way to do this would probably be to compare the absolute address
- with a segment relative relocation of the same symbol. */
-
-extern int __text_start;
-extern int __data_start;
-
-/* The exception index table location. */
-extern __EIT_entry __exidx_start;
-extern __EIT_entry __exidx_end;
-
-/* ABI defined personality routines. */
-extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr0 (_Unwind_State,
- _Unwind_Control_Block *, _Unwind_Context *);// __attribute__((weak));
-extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr1 (_Unwind_State,
- _Unwind_Control_Block *, _Unwind_Context *) __attribute__((weak));
-extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr2 (_Unwind_State,
- _Unwind_Control_Block *, _Unwind_Context *) __attribute__((weak));
-
-/* ABI defined routine to store a virtual register to memory. */
-
-_Unwind_VRS_Result _Unwind_VRS_Get (_Unwind_Context *context,
- _Unwind_VRS_RegClass regclass,
- _uw regno,
- _Unwind_VRS_DataRepresentation representation,
- void *valuep)
-{
- phase1_vrs *vrs = (phase1_vrs *) context;
-
- switch (regclass)
- {
- case _UVRSC_CORE:
- if (representation != _UVRSD_UINT32
- || regno > 15)
- return _UVRSR_FAILED;
- *(_uw *) valuep = vrs->core.r[regno];
- return _UVRSR_OK;
-
- case _UVRSC_VFP:
- case _UVRSC_FPA:
- case _UVRSC_WMMXD:
- case _UVRSC_WMMXC:
- return _UVRSR_NOT_IMPLEMENTED;
-
- default:
- return _UVRSR_FAILED;
- }
-}
-
-
-/* ABI defined function to load a virtual register from memory. */
-
-_Unwind_VRS_Result _Unwind_VRS_Set (_Unwind_Context *context,
- _Unwind_VRS_RegClass regclass,
- _uw regno,
- _Unwind_VRS_DataRepresentation representation,
- void *valuep)
-{
- phase1_vrs *vrs = (phase1_vrs *) context;
-
- switch (regclass)
- {
- case _UVRSC_CORE:
- if (representation != _UVRSD_UINT32
- || regno > 15)
- return _UVRSR_FAILED;
-
- vrs->core.r[regno] = *(_uw *) valuep;
- return _UVRSR_OK;
-
- case _UVRSC_VFP:
- case _UVRSC_FPA:
- case _UVRSC_WMMXD:
- case _UVRSC_WMMXC:
- return _UVRSR_NOT_IMPLEMENTED;
-
- default:
- return _UVRSR_FAILED;
- }
-}
-
-
-/* ABI defined function to pop registers off the stack. */
-
-_Unwind_VRS_Result _Unwind_VRS_Pop (_Unwind_Context *context,
- _Unwind_VRS_RegClass regclass,
- _uw discriminator,
- _Unwind_VRS_DataRepresentation representation)
-{
- phase1_vrs *vrs = (phase1_vrs *) context;
-
- switch (regclass)
- {
- case _UVRSC_CORE:
- {
- _uw *ptr;
- _uw mask;
- int i;
-
- if (representation != _UVRSD_UINT32)
- return _UVRSR_FAILED;
-
- mask = discriminator & 0xffff;
- ptr = (_uw *) vrs->core.r[R_SP];
- /* Pop the requested registers. */
- for (i = 0; i < 16; i++)
- {
- if (mask & (1 << i))
- vrs->core.r[i] = *(ptr++);
- }
- /* Writeback the stack pointer value if it wasn't restored. */
- if ((mask & (1 << R_SP)) == 0)
- vrs->core.r[R_SP] = (_uw) ptr;
- }
- return _UVRSR_OK;
-
- case _UVRSC_VFP:
- {
- _uw start = discriminator >> 16;
- _uw count = discriminator & 0xffff;
- struct vfp_regs tmp;
- _uw *sp;
- _uw *dest;
-
- if ((representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE)
- || start + count > 16)
- return _UVRSR_FAILED;
-
- if (vrs->demand_save_flags & DEMAND_SAVE_VFP)
- {
- /* Demand-save resisters for stage1. */
- vrs->demand_save_flags &= ~DEMAND_SAVE_VFP;
- __gnu_Unwind_Save_VFP (&vrs->vfp);
- }
-
- /* Restore the registers from the stack. Do this by saving the
- current VFP registers to a memory area, moving the in-memory
- values into that area, and restoring from the whole area.
- For _UVRSD_VFPX we assume FSTMX standard format 1. */
- __gnu_Unwind_Save_VFP (&tmp);
-
- /* The stack address is only guaranteed to be word aligned, so
- we can't use doubleword copies. */
- sp = (_uw *) vrs->core.r[R_SP];
- dest = (_uw *) &tmp.d[start];
- count *= 2;
- while (count--)
- *(dest++) = *(sp++);
-
- /* Skip the pad word */
- if (representation == _UVRSD_VFPX)
- sp++;
-
- /* Set the new stack pointer. */
- vrs->core.r[R_SP] = (_uw) sp;
-
- /* Reload the registers. */
- __gnu_Unwind_Restore_VFP (&tmp);
- }
- return _UVRSR_OK;
-
- case _UVRSC_FPA:
- case _UVRSC_WMMXD:
- case _UVRSC_WMMXC:
- return _UVRSR_NOT_IMPLEMENTED;
-
- default:
- return _UVRSR_FAILED;
- }
-}
-
-
-/* Core unwinding functions. */
-
-/* Calculate the address encoded by a 31-bit self-relative offset at address
- P. */
-static inline _uw
-selfrel_offset31 (const _uw *p)
-{
- _uw offset;
-
- offset = *p;
- /* Sign extend to 32 bits. */
- if (offset & (1 << 30))
- offset |= 1u << 31;
- else
- offset &= ~(1u << 31);
-
- return offset + (_uw) p;
-}
-
-
-/* Perform a binary search for RETURN_ADDRESS in TABLE. The table contains
- NREC entries. */
-
-static const __EIT_entry *
-search_EIT_table (const __EIT_entry * table, int nrec, _uw return_address)
-{
- _uw next_fn;
- _uw this_fn;
- int n, left, right;
-
- if (nrec == 0)
- return (__EIT_entry *) 0;
-
- left = 0;
- right = nrec - 1;
-
- while (1)
- {
- n = (left + right) / 2;
- this_fn = selfrel_offset31 (&table[n].fnoffset);
- if (n != nrec - 1)
- next_fn = selfrel_offset31 (&table[n + 1].fnoffset) - 1;
- else
- next_fn = (_uw)0 - 1;
-
- if (return_address < this_fn)
- {
- if (n == left)
- return (__EIT_entry *) 0;
- right = n - 1;
- }
- else if (return_address <= next_fn)
- return &table[n];
- else
- left = n + 1;
- }
-}
-
-/* Find the exception index table eintry for the given address.
- Fill in the relevant fields of the UCB.
- Returns _URC_FAILURE if an error occurred, _URC_OK on success. */
-
-static _Unwind_Reason_Code
-get_eit_entry (_Unwind_Control_Block *ucbp, _uw return_address)
-{
- const __EIT_entry * eitp;
- int nrec;
-
- /* The return address is the address of the instruction following the
- call instruction (plus one in thumb mode). If this was the last
- instruction in the function the address will lie in the following
- function. Subtract 2 from the address so that it points within the call
- instruction itself. */
- return_address -= 2;
-
- if (__gnu_Unwind_Find_exidx)
- {
- eitp = (const __EIT_entry *) __gnu_Unwind_Find_exidx (return_address,
- &nrec);
- if (!eitp)
- {
- UCB_PR_ADDR (ucbp) = 0;
- return _URC_FAILURE;
- }
- }
- else
- {
- eitp = &__exidx_start;
- nrec = &__exidx_end - &__exidx_start;
- }
-
- eitp = search_EIT_table (eitp, nrec, return_address);
-
- if (!eitp)
- {
- UCB_PR_ADDR (ucbp) = 0;
- return _URC_FAILURE;
- }
- ucbp->pr_cache.fnstart = selfrel_offset31 (&eitp->fnoffset);
-
- /* Can this frame be unwound at all? */
- if (eitp->content == EXIDX_CANTUNWIND)
- {
- UCB_PR_ADDR (ucbp) = 0;
- return _URC_END_OF_STACK;
- }
-
- /* Obtain the address of the "real" __EHT_Header word. */
-
- if (eitp->content & uint32_highbit)
- {
- /* It is immediate data. */
- ucbp->pr_cache.ehtp = (_Unwind_EHT_Header *)&eitp->content;
- ucbp->pr_cache.additional = 1;
- }
- else
- {
- /* The low 31 bits of the content field are a self-relative
- offset to an _Unwind_EHT_Entry structure. */
- ucbp->pr_cache.ehtp =
- (_Unwind_EHT_Header *) selfrel_offset31 (&eitp->content);
- ucbp->pr_cache.additional = 0;
- }
-
- /* Discover the personality routine address. */
- if (*ucbp->pr_cache.ehtp & (1u << 31))
- {
- /* One of the predefined standard routines. */
- _uw idx = (*(_uw *) ucbp->pr_cache.ehtp >> 24) & 0xf;
- if (idx == 0)
- UCB_PR_ADDR (ucbp) = (_uw) &__aeabi_unwind_cpp_pr0;
- else if (idx == 1)
- UCB_PR_ADDR (ucbp) = (_uw) &__aeabi_unwind_cpp_pr1;
- else if (idx == 2)
- UCB_PR_ADDR (ucbp) = (_uw) &__aeabi_unwind_cpp_pr2;
- else
- { /* Failed */
- UCB_PR_ADDR (ucbp) = 0;
- return _URC_FAILURE;
- }
- }
- else
- {
- /* Execute region offset to PR */
- UCB_PR_ADDR (ucbp) = selfrel_offset31 (ucbp->pr_cache.ehtp);
- }
- return _URC_OK;
-}
-
-
-/* Perform phase2 unwinding. VRS is the initial virtual register state. */
-
-static void __attribute__((noreturn))
-unwind_phase2 (_Unwind_Control_Block * ucbp, phase2_vrs * vrs)
-{
- _Unwind_Reason_Code pr_result;
-
- do
- {
- /* Find the entry for this routine. */
- if (get_eit_entry (ucbp, vrs->core.r[R_PC]) != _URC_OK)
- abort ();
-
- UCB_SAVED_CALLSITE_ADDR (ucbp) = vrs->core.r[R_PC];
-
- /* Call the pr to decide what to do. */
- pr_result = ((personality_routine) UCB_PR_ADDR (ucbp))
- (_US_UNWIND_FRAME_STARTING, ucbp, (_Unwind_Context *) vrs);
- }
- while (pr_result == _URC_CONTINUE_UNWIND);
-
- if (pr_result != _URC_INSTALL_CONTEXT)
- abort();
-
- restore_core_regs (&vrs->core);
-}
-
-/* Perform phase2 forced unwinding. */
-
-static _Unwind_Reason_Code
-unwind_phase2_forced (_Unwind_Control_Block *ucbp, phase2_vrs *entry_vrs,
- int resuming)
-{
- _Unwind_Stop_Fn stop_fn = (_Unwind_Stop_Fn) UCB_FORCED_STOP_FN (ucbp);
- void *stop_arg = (void *)UCB_FORCED_STOP_ARG (ucbp);
- _Unwind_Reason_Code pr_result = 0;
- /* We use phase1_vrs here even though we do not demand save, for the
- prev_sp field. */
- phase1_vrs saved_vrs, next_vrs;
-
- /* Save the core registers. */
- saved_vrs.core = entry_vrs->core;
- /* We don't need to demand-save the non-core registers, because we
- unwind in a single pass. */
- saved_vrs.demand_save_flags = 0;
-
- /* Unwind until we reach a propagation barrier. */
- do
- {
- _Unwind_State action;
- _Unwind_Reason_Code entry_code;
- _Unwind_Reason_Code stop_code;
-
- /* Find the entry for this routine. */
- entry_code = get_eit_entry (ucbp, saved_vrs.core.r[R_PC]);
-
- if (resuming)
- {
- action = _US_UNWIND_FRAME_RESUME | _US_FORCE_UNWIND;
- resuming = 0;
- }
- else
- action = _US_UNWIND_FRAME_STARTING | _US_FORCE_UNWIND;
-
- if (entry_code == _URC_OK)
- {
- UCB_SAVED_CALLSITE_ADDR (ucbp) = saved_vrs.core.r[R_PC];
-
- next_vrs = saved_vrs;
-
- /* Call the pr to decide what to do. */
- pr_result = ((personality_routine) UCB_PR_ADDR (ucbp))
- (action, ucbp, (void *) &next_vrs);
-
- saved_vrs.prev_sp = next_vrs.core.r[R_SP];
- }
- else
- {
- /* Treat any failure as the end of unwinding, to cope more
- gracefully with missing EH information. Mixed EH and
- non-EH within one object will usually result in failure,
- because the .ARM.exidx tables do not indicate the end
- of the code to which they apply; but mixed EH and non-EH
- shared objects should return an unwind failure at the
- entry of a non-EH shared object. */
- action |= _US_END_OF_STACK;
-
- saved_vrs.prev_sp = saved_vrs.core.r[R_SP];
- }
-
- stop_code = stop_fn (1, action, ucbp->exception_class, ucbp,
- (void *)&saved_vrs, stop_arg);
- if (stop_code != _URC_NO_REASON)
- return _URC_FAILURE;
-
- if (entry_code != _URC_OK)
- return entry_code;
-
- saved_vrs = next_vrs;
- }
- while (pr_result == _URC_CONTINUE_UNWIND);
-
- if (pr_result != _URC_INSTALL_CONTEXT)
- {
- /* Some sort of failure has occurred in the pr and probably the
- pr returned _URC_FAILURE. */
- return _URC_FAILURE;
- }
-
- restore_core_regs (&saved_vrs.core);
-}
-
-/* This is a very limited implementation of _Unwind_GetCFA. It returns
- the stack pointer as it is about to be unwound, and is only valid
- while calling the stop function during forced unwinding. If the
- current personality routine result is going to run a cleanup, this
- will not be the CFA; but when the frame is really unwound, it will
- be. */
-
-_Unwind_Word
-_Unwind_GetCFA (_Unwind_Context *context)
-{
- return ((phase1_vrs *) context)->prev_sp;
-}
-
-/* Perform phase1 unwinding. UCBP is the exception being thrown, and
- entry_VRS is the register state on entry to _Unwind_RaiseException. */
-
-_Unwind_Reason_Code
-__gnu_Unwind_RaiseException (_Unwind_Control_Block *, phase2_vrs *);
-
-_Unwind_Reason_Code
-__gnu_Unwind_RaiseException (_Unwind_Control_Block * ucbp,
- phase2_vrs * entry_vrs)
-{
- phase1_vrs saved_vrs;
- _Unwind_Reason_Code pr_result;
-
- /* Set the pc to the call site. */
- entry_vrs->core.r[R_PC] = entry_vrs->core.r[R_LR];
-
- /* Save the core registers. */
- saved_vrs.core = entry_vrs->core;
- /* Set demand-save flags. */
- saved_vrs.demand_save_flags = ~(_uw) 0;
-
- /* Unwind until we reach a propagation barrier. */
- do
- {
- /* Find the entry for this routine. */
- if (get_eit_entry (ucbp, saved_vrs.core.r[R_PC]) != _URC_OK)
- return _URC_FAILURE;
-
- /* Call the pr to decide what to do. */
- pr_result = ((personality_routine) UCB_PR_ADDR (ucbp))
- (_US_VIRTUAL_UNWIND_FRAME, ucbp, (void *) &saved_vrs);
- }
- while (pr_result == _URC_CONTINUE_UNWIND);
-
- /* We've unwound as far as we want to go, so restore the original
- register state. */
- restore_non_core_regs (&saved_vrs);
- if (pr_result != _URC_HANDLER_FOUND)
- {
- /* Some sort of failure has occurred in the pr and probably the
- pr returned _URC_FAILURE. */
- return _URC_FAILURE;
- }
-
- unwind_phase2 (ucbp, entry_vrs);
-}
-
-/* Resume unwinding after a cleanup has been run. UCBP is the exception
- being thrown and ENTRY_VRS is the register state on entry to
- _Unwind_Resume. */
-_Unwind_Reason_Code
-__gnu_Unwind_ForcedUnwind (_Unwind_Control_Block *,
- _Unwind_Stop_Fn, void *, phase2_vrs *);
-
-_Unwind_Reason_Code
-__gnu_Unwind_ForcedUnwind (_Unwind_Control_Block *ucbp,
- _Unwind_Stop_Fn stop_fn, void *stop_arg,
- phase2_vrs *entry_vrs)
-{
- UCB_FORCED_STOP_FN (ucbp) = (_uw) stop_fn;
- UCB_FORCED_STOP_ARG (ucbp) = (_uw) stop_arg;
-
- /* Set the pc to the call site. */
- entry_vrs->core.r[R_PC] = entry_vrs->core.r[R_LR];
-
- return unwind_phase2_forced (ucbp, entry_vrs, 0);
-}
-
-_Unwind_Reason_Code
-__gnu_Unwind_Resume (_Unwind_Control_Block *, phase2_vrs *);
-
-_Unwind_Reason_Code
-__gnu_Unwind_Resume (_Unwind_Control_Block * ucbp, phase2_vrs * entry_vrs)
-{
- _Unwind_Reason_Code pr_result;
-
- /* Recover the saved address. */
- entry_vrs->core.r[R_PC] = UCB_SAVED_CALLSITE_ADDR (ucbp);
-
- if (UCB_FORCED_STOP_FN (ucbp))
- {
- unwind_phase2_forced (ucbp, entry_vrs, 1);
-
- /* We can't return failure at this point. */
- abort ();
- }
-
- /* Call the cached PR. */
- pr_result = ((personality_routine) UCB_PR_ADDR (ucbp))
- (_US_UNWIND_FRAME_RESUME, ucbp, (_Unwind_Context *) entry_vrs);
-
- switch (pr_result)
- {
- case _URC_INSTALL_CONTEXT:
- /* Upload the registers to enter the landing pad. */
- restore_core_regs (&entry_vrs->core);
-
- case _URC_CONTINUE_UNWIND:
- /* Continue unwinding the next frame. */
- unwind_phase2 (ucbp, entry_vrs);
-
- default:
- abort ();
- }
-}
-
-_Unwind_Reason_Code
-__gnu_Unwind_Resume_or_Rethrow (_Unwind_Control_Block *, phase2_vrs *);
-
-_Unwind_Reason_Code
-__gnu_Unwind_Resume_or_Rethrow (_Unwind_Control_Block * ucbp,
- phase2_vrs * entry_vrs)
-{
- if (!UCB_FORCED_STOP_FN (ucbp))
- return __gnu_Unwind_RaiseException (ucbp, entry_vrs);
-
- /* Set the pc to the call site. */
- entry_vrs->core.r[R_PC] = entry_vrs->core.r[R_LR];
- /* Continue unwinding the next frame. */
- return unwind_phase2_forced (ucbp, entry_vrs, 0);
-}
-
-/* Clean up an exception object when unwinding is complete. */
-void
-_Unwind_Complete (_Unwind_Control_Block * ucbp __attribute__((unused)))
-{
-}
-
-
-/* Get the _Unwind_Control_Block from an _Unwind_Context. */
-
-static inline _Unwind_Control_Block *
-unwind_UCB_from_context (_Unwind_Context * context)
-{
- return (_Unwind_Control_Block *) _Unwind_GetGR (context, R_IP);
-}
-
-
-/* Free an exception. */
-
-void
-_Unwind_DeleteException (_Unwind_Exception * exc)
-{
- if (exc->exception_cleanup)
- (*exc->exception_cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exc);
-}
-
-
-/* Perform stack backtrace through unwind data. */
-_Unwind_Reason_Code
-__gnu_Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument,
- phase2_vrs * entry_vrs);
-_Unwind_Reason_Code
-__gnu_Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument,
- phase2_vrs * entry_vrs)
-{
- phase1_vrs saved_vrs;
- _Unwind_Reason_Code code;
-
- _Unwind_Control_Block ucb;
- _Unwind_Control_Block *ucbp = &ucb;
-
- /* Set the pc to the call site. */
- entry_vrs->core.r[R_PC] = entry_vrs->core.r[R_LR];
-
- /* Save the core registers. */
- saved_vrs.core = entry_vrs->core;
- /* Set demand-save flags. */
- saved_vrs.demand_save_flags = ~(_uw) 0;
-
- do
- {
- /* Find the entry for this routine. */
- if (get_eit_entry (ucbp, saved_vrs.core.r[R_PC]) != _URC_OK)
- {
- code = _URC_FAILURE;
- goto finish;
- }
-
- /* The dwarf unwinder assumes the context structure holds things
- like the function and LSDA pointers. The ARM implementation
- caches these in the exception header (UCB). To avoid
- rewriting everything we make the virtual IP register point at
- the UCB. */
- _Unwind_SetGR((_Unwind_Context *)&saved_vrs, 12, (_Unwind_Ptr) ucbp);
-
- /* Call trace function. */
- if ((*trace) ((_Unwind_Context *) &saved_vrs, trace_argument)
- != _URC_NO_REASON)
- {
- code = _URC_FAILURE;
- goto finish;
- }
-
- /* Call the pr to decide what to do. */
- code = ((personality_routine) UCB_PR_ADDR (ucbp))
- (_US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND,
- ucbp, (void *) &saved_vrs);
- }
- while (code != _URC_END_OF_STACK
- && code != _URC_FAILURE);
-
- finish:
- restore_non_core_regs (&saved_vrs);
- return code;
-}
-
-
-/* Common implementation for ARM ABI defined personality routines.
- ID is the index of the personality routine, other arguments are as defined
- by __aeabi_unwind_cpp_pr{0,1,2}. */
-
-static _Unwind_Reason_Code
-__gnu_unwind_pr_common (_Unwind_State state,
- _Unwind_Control_Block *ucbp,
- _Unwind_Context *context,
- int id)
-{
- __gnu_unwind_state uws;
- _uw *data;
- _uw offset;
- _uw len;
- _uw rtti_count;
- int phase2_call_unexpected_after_unwind = 0;
- int in_range = 0;
- int forced_unwind = state & _US_FORCE_UNWIND;
-
- state &= _US_ACTION_MASK;
-
- data = (_uw *) ucbp->pr_cache.ehtp;
- uws.data = *(data++);
- uws.next = data;
- if (id == 0)
- {
- uws.data <<= 8;
- uws.words_left = 0;
- uws.bytes_left = 3;
- }
- else
- {
- uws.words_left = (uws.data >> 16) & 0xff;
- uws.data <<= 16;
- uws.bytes_left = 2;
- data += uws.words_left;
- }
-
- /* Restore the saved pointer. */
- if (state == _US_UNWIND_FRAME_RESUME)
- data = (_uw *) ucbp->cleanup_cache.bitpattern[0];
-
- if ((ucbp->pr_cache.additional & 1) == 0)
- {
- /* Process descriptors. */
- while (*data)
- {
- _uw addr;
- _uw fnstart;
-
- if (id == 2)
- {
- len = ((EHT32 *) data)->length;
- offset = ((EHT32 *) data)->offset;
- data += 2;
- }
- else
- {
- len = ((EHT16 *) data)->length;
- offset = ((EHT16 *) data)->offset;
- data++;
- }
-
- fnstart = ucbp->pr_cache.fnstart + (offset & ~1);
- addr = _Unwind_GetGR (context, R_PC);
- in_range = (fnstart <= addr && addr < fnstart + (len & ~1));
-
- switch (((offset & 1) << 1) | (len & 1))
- {
- case 0:
- /* Cleanup. */
- if (state != _US_VIRTUAL_UNWIND_FRAME
- && in_range)
- {
- /* Cleanup in range, and we are running cleanups. */
- _uw lp;
-
- /* Landing pad address is 31-bit pc-relative offset. */
- lp = selfrel_offset31 (data);
- data++;
- /* Save the exception data pointer. */
- ucbp->cleanup_cache.bitpattern[0] = (_uw) data;
- if (!__cxa_begin_cleanup (ucbp))
- return _URC_FAILURE;
- /* Setup the VRS to enter the landing pad. */
- _Unwind_SetGR (context, R_PC, lp);
- return _URC_INSTALL_CONTEXT;
- }
- /* Cleanup not in range, or we are in stage 1. */
- data++;
- break;
-
- case 1:
- /* Catch handler. */
- if (state == _US_VIRTUAL_UNWIND_FRAME)
- {
- if (in_range)
- {
- /* Check for a barrier. */
- _uw rtti;
- void *matched;
-
- /* Check for no-throw areas. */
- if (data[1] == (_uw) -2)
- return _URC_FAILURE;
-
- /* The thrown object immediately follows the ECB. */
- matched = (void *)(ucbp + 1);
- if (data[1] != (_uw) -1)
- {
- /* Match a catch specification. */
- rtti = _Unwind_decode_target2 ((_uw) &data[1]);
- if (!__cxa_type_match (ucbp, (type_info *) rtti,
- &matched))
- matched = (void *)0;
- }
-
- if (matched)
- {
- ucbp->barrier_cache.sp =
- _Unwind_GetGR (context, R_SP);
- ucbp->barrier_cache.bitpattern[0] = (_uw) matched;
- ucbp->barrier_cache.bitpattern[1] = (_uw) data;
- return _URC_HANDLER_FOUND;
- }
- }
- /* Handler out of range, or not matched. */
- }
- else if (ucbp->barrier_cache.sp == _Unwind_GetGR (context, R_SP)
- && ucbp->barrier_cache.bitpattern[1] == (_uw) data)
- {
- /* Matched a previous propagation barrier. */
- _uw lp;
-
- /* Setup for entry to the handler. */
- lp = selfrel_offset31 (data);
- _Unwind_SetGR (context, R_PC, lp);
- _Unwind_SetGR (context, 0, (_uw) ucbp);
- return _URC_INSTALL_CONTEXT;
- }
- /* Catch handler not matched. Advance to the next descriptor. */
- data += 2;
- break;
-
- case 2:
- rtti_count = data[0] & 0x7fffffff;
- /* Exception specification. */
- if (state == _US_VIRTUAL_UNWIND_FRAME)
- {
- if (in_range && (!forced_unwind || !rtti_count))
- {
- /* Match against the exception specification. */
- _uw i;
- _uw rtti;
- void *matched;
-
- for (i = 0; i < rtti_count; i++)
- {
- matched = (void *)(ucbp + 1);
- rtti = _Unwind_decode_target2 ((_uw) &data[i + 1]);
- if (__cxa_type_match (ucbp, (type_info *) rtti,
- &matched))
- break;
- }
-
- if (i == rtti_count)
- {
- /* Exception does not match the spec. */
- ucbp->barrier_cache.sp =
- _Unwind_GetGR (context, R_SP);
- ucbp->barrier_cache.bitpattern[0] = (_uw) matched;
- ucbp->barrier_cache.bitpattern[1] = (_uw) data;
- return _URC_HANDLER_FOUND;
- }
- }
- /* Handler out of range, or exception is permitted. */
- }
- else if (ucbp->barrier_cache.sp == _Unwind_GetGR (context, R_SP)
- && ucbp->barrier_cache.bitpattern[1] == (_uw) data)
- {
- /* Matched a previous propagation barrier. */
- _uw lp;
- /* Record the RTTI list for __cxa_call_unexpected. */
- ucbp->barrier_cache.bitpattern[1] = rtti_count;
- ucbp->barrier_cache.bitpattern[2] = 0;
- ucbp->barrier_cache.bitpattern[3] = 4;
- ucbp->barrier_cache.bitpattern[4] = (_uw) &data[1];
-
- if (data[0] & uint32_highbit)
- phase2_call_unexpected_after_unwind = 1;
- else
- {
- data += rtti_count + 1;
- /* Setup for entry to the handler. */
- lp = selfrel_offset31 (data);
- data++;
- _Unwind_SetGR (context, R_PC, lp);
- _Unwind_SetGR (context, 0, (_uw) ucbp);
- return _URC_INSTALL_CONTEXT;
- }
- }
- if (data[0] & uint32_highbit)
- data++;
- data += rtti_count + 1;
- break;
-
- default:
- /* Should never happen. */
- return _URC_FAILURE;
- }
- /* Finished processing this descriptor. */
- }
- }
-
- if (__gnu_unwind_execute (context, &uws) != _URC_OK)
- return _URC_FAILURE;
-
- if (phase2_call_unexpected_after_unwind)
- {
- /* Enter __cxa_unexpected as if called from the call site. */
- _Unwind_SetGR (context, R_LR, _Unwind_GetGR (context, R_PC));
- _Unwind_SetGR (context, R_PC, (_uw) &__cxa_call_unexpected);
- return _URC_INSTALL_CONTEXT;
- }
-
- return _URC_CONTINUE_UNWIND;
-}
-
-
-/* ABI defined personality routine entry points. */
-
-_Unwind_Reason_Code
-__aeabi_unwind_cpp_pr0 (_Unwind_State state,
- _Unwind_Control_Block *ucbp,
- _Unwind_Context *context)
-{
- return __gnu_unwind_pr_common (state, ucbp, context, 0);
-}
-
-_Unwind_Reason_Code
-__aeabi_unwind_cpp_pr1 (_Unwind_State state,
- _Unwind_Control_Block *ucbp,
- _Unwind_Context *context)
-{
- return __gnu_unwind_pr_common (state, ucbp, context, 1);
-}
-
-_Unwind_Reason_Code
-__aeabi_unwind_cpp_pr2 (_Unwind_State state,
- _Unwind_Control_Block *ucbp,
- _Unwind_Context *context)
-{
- return __gnu_unwind_pr_common (state, ucbp, context, 2);
-}
-
-/* These two should never be used. */
-_Unwind_Ptr
-_Unwind_GetDataRelBase (_Unwind_Context *context __attribute__ ((unused)))
-{
- abort ();
-}
-
-_Unwind_Ptr
-_Unwind_GetTextRelBase (_Unwind_Context *context __attribute__ ((unused)))
-{
- abort ();
-}
diff --git a/gcc-4.2.1/gcc/config/arm/unwind-arm.h b/gcc-4.2.1/gcc/config/arm/unwind-arm.h
deleted file mode 100644
index cf94c3463..000000000
--- a/gcc-4.2.1/gcc/config/arm/unwind-arm.h
+++ /dev/null
@@ -1,277 +0,0 @@
-/* Header file for the ARM EABI unwinder
- Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
- Contributed by Paul Brook
-
- 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 into combinations with other programs,
- and to distribute those combinations 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 a combine
- executable.)
-
- 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, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* Language-independent unwinder header public defines. This contains both
- ABI defined objects, and GNU support routines. */
-
-#ifndef UNWIND_ARM_H
-#define UNWIND_ARM_H
-
-#define __ARM_EABI_UNWINDER__ 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
- typedef unsigned _Unwind_Word __attribute__((__mode__(__word__)));
- typedef signed _Unwind_Sword __attribute__((__mode__(__word__)));
- typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__)));
- typedef unsigned _Unwind_Internal_Ptr __attribute__((__mode__(__pointer__)));
- typedef _Unwind_Word _uw;
- typedef unsigned _uw64 __attribute__((mode(__DI__)));
- typedef unsigned _uw16 __attribute__((mode(__HI__)));
- typedef unsigned _uw8 __attribute__((mode(__QI__)));
-
- typedef enum
- {
- _URC_OK = 0, /* operation completed successfully */
- _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
- _URC_END_OF_STACK = 5,
- _URC_HANDLER_FOUND = 6,
- _URC_INSTALL_CONTEXT = 7,
- _URC_CONTINUE_UNWIND = 8,
- _URC_FAILURE = 9 /* unspecified failure of some kind */
- }
- _Unwind_Reason_Code;
-
- typedef enum
- {
- _US_VIRTUAL_UNWIND_FRAME = 0,
- _US_UNWIND_FRAME_STARTING = 1,
- _US_UNWIND_FRAME_RESUME = 2,
- _US_ACTION_MASK = 3,
- _US_FORCE_UNWIND = 8,
- _US_END_OF_STACK = 16
- }
- _Unwind_State;
-
- /* Provided only for for compatibility with existing code. */
- typedef int _Unwind_Action;
-#define _UA_SEARCH_PHASE 1
-#define _UA_CLEANUP_PHASE 2
-#define _UA_HANDLER_FRAME 4
-#define _UA_FORCE_UNWIND 8
-#define _UA_END_OF_STACK 16
-#define _URC_NO_REASON _URC_OK
-
- typedef struct _Unwind_Control_Block _Unwind_Control_Block;
- typedef struct _Unwind_Context _Unwind_Context;
- typedef _uw _Unwind_EHT_Header;
-
-
- /* UCB: */
-
- struct _Unwind_Control_Block
- {
- char exception_class[8];
- void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block *);
- /* Unwinder cache, private fields for the unwinder's use */
- struct
- {
- _uw reserved1; /* Forced unwind stop fn, 0 if not forced */
- _uw reserved2; /* Personality routine address */
- _uw reserved3; /* Saved callsite address */
- _uw reserved4; /* Forced unwind stop arg */
- _uw reserved5;
- }
- unwinder_cache;
- /* Propagation barrier cache (valid after phase 1): */
- struct
- {
- _uw sp;
- _uw bitpattern[5];
- }
- barrier_cache;
- /* Cleanup cache (preserved over cleanup): */
- struct
- {
- _uw bitpattern[4];
- }
- cleanup_cache;
- /* Pr cache (for pr's benefit): */
- struct
- {
- _uw fnstart; /* function start address */
- _Unwind_EHT_Header *ehtp; /* pointer to EHT entry header word */
- _uw additional; /* additional data */
- _uw reserved1;
- }
- pr_cache;
- long long int :0; /* Force alignment to 8-byte boundary */
- };
-
- /* Virtual Register Set*/
-
- typedef enum
- {
- _UVRSC_CORE = 0, /* integer register */
- _UVRSC_VFP = 1, /* vfp */
- _UVRSC_FPA = 2, /* fpa */
- _UVRSC_WMMXD = 3, /* Intel WMMX data register */
- _UVRSC_WMMXC = 4 /* Intel WMMX control register */
- }
- _Unwind_VRS_RegClass;
-
- typedef enum
- {
- _UVRSD_UINT32 = 0,
- _UVRSD_VFPX = 1,
- _UVRSD_FPAX = 2,
- _UVRSD_UINT64 = 3,
- _UVRSD_FLOAT = 4,
- _UVRSD_DOUBLE = 5
- }
- _Unwind_VRS_DataRepresentation;
-
- typedef enum
- {
- _UVRSR_OK = 0,
- _UVRSR_NOT_IMPLEMENTED = 1,
- _UVRSR_FAILED = 2
- }
- _Unwind_VRS_Result;
-
- /* Frame unwinding state. */
- typedef struct
- {
- /* The current word (bytes packed msb first). */
- _uw data;
- /* Pointer to the next word of data. */
- _uw *next;
- /* The number of bytes left in this word. */
- _uw8 bytes_left;
- /* The number of words pointed to by ptr. */
- _uw8 words_left;
- }
- __gnu_unwind_state;
-
- typedef _Unwind_Reason_Code (*personality_routine) (_Unwind_State,
- _Unwind_Control_Block *, _Unwind_Context *);
-
- _Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *, _Unwind_VRS_RegClass,
- _uw, _Unwind_VRS_DataRepresentation,
- void *);
-
- _Unwind_VRS_Result _Unwind_VRS_Get(_Unwind_Context *, _Unwind_VRS_RegClass,
- _uw, _Unwind_VRS_DataRepresentation,
- void *);
-
- _Unwind_VRS_Result _Unwind_VRS_Pop(_Unwind_Context *, _Unwind_VRS_RegClass,
- _uw, _Unwind_VRS_DataRepresentation);
-
-
- /* Support functions for the PR. */
-#define _Unwind_Exception _Unwind_Control_Block
- typedef char _Unwind_Exception_Class[8];
-
- void * _Unwind_GetLanguageSpecificData (_Unwind_Context *);
- _Unwind_Ptr _Unwind_GetRegionStart (_Unwind_Context *);
-
- /* These two should never be used. */
- _Unwind_Ptr _Unwind_GetDataRelBase (_Unwind_Context *);
- _Unwind_Ptr _Unwind_GetTextRelBase (_Unwind_Context *);
-
- /* Interface functions: */
- _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Control_Block *ucbp);
- void __attribute__((noreturn)) _Unwind_Resume(_Unwind_Control_Block *ucbp);
- _Unwind_Reason_Code _Unwind_Resume_or_Rethrow (_Unwind_Control_Block *ucbp);
-
- typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)
- (int, _Unwind_Action, _Unwind_Exception_Class,
- _Unwind_Control_Block *, struct _Unwind_Context *, void *);
- _Unwind_Reason_Code _Unwind_ForcedUnwind (_Unwind_Control_Block *,
- _Unwind_Stop_Fn, void *);
- /* @@@ Use unwind data to perform a stack backtrace. The trace callback
- is called for every stack frame in the call chain, but no cleanup
- actions are performed. */
- typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn) (_Unwind_Context *, void *);
- _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn, void*);
-
- _Unwind_Word _Unwind_GetCFA (struct _Unwind_Context *);
- void _Unwind_Complete(_Unwind_Control_Block *ucbp);
- void _Unwind_DeleteException (_Unwind_Exception *);
-
- _Unwind_Reason_Code __gnu_unwind_frame (_Unwind_Control_Block *,
- _Unwind_Context *);
- _Unwind_Reason_Code __gnu_unwind_execute (_Unwind_Context *,
- __gnu_unwind_state *);
-
- /* Decode an R_ARM_TARGET2 relocation. */
- static inline _Unwind_Word
- _Unwind_decode_target2 (_Unwind_Word ptr)
- {
- _Unwind_Word tmp;
-
- tmp = *(_Unwind_Word *) ptr;
- /* Zero values are always NULL. */
- if (!tmp)
- return 0;
-
-#if defined(linux) || defined(__NetBSD__)
- /* Pc-relative indirect. */
- tmp += ptr;
- tmp = *(_Unwind_Word *) tmp;
-#elif defined(__symbian__)
- /* Absolute pointer. Nothing more to do. */
-#else
- /* Pc-relative pointer. */
- tmp += ptr;
-#endif
- return tmp;
- }
-
- static inline _Unwind_Word
- _Unwind_GetGR (_Unwind_Context *context, int regno)
- {
- _uw val;
- _Unwind_VRS_Get (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
- return val;
- }
-
- /* Return the address of the instruction, not the actual IP value. */
-#define _Unwind_GetIP(context) \
- (_Unwind_GetGR (context, 15) & ~(_Unwind_Word)1)
-
-#define _Unwind_GetIPInfo(context, ip_before_insn) \
- (*ip_before_insn = 0, _Unwind_GetGR (context, 15) & ~(_Unwind_Word)1)
-
- static inline void
- _Unwind_SetGR (_Unwind_Context *context, int regno, _Unwind_Word val)
- {
- _Unwind_VRS_Set (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
- }
-
- /* The dwarf unwinder doesn't understand arm/thumb state. We assume the
- landing pad uses the same instruction set as the call site. */
-#define _Unwind_SetIP(context, val) \
- _Unwind_SetGR (context, 15, val | (_Unwind_GetGR (context, 15) & 1))
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* defined UNWIND_ARM_H */
diff --git a/gcc-4.2.1/gcc/config/arm/vfp.md b/gcc-4.2.1/gcc/config/arm/vfp.md
deleted file mode 100644
index 2380c83ca..000000000
--- a/gcc-4.2.1/gcc/config/arm/vfp.md
+++ /dev/null
@@ -1,841 +0,0 @@
-;; ARM VFP coprocessor Machine Description
-;; Copyright (C) 2003, 2005 Free Software Foundation, Inc.
-;; Written by CodeSourcery, LLC.
-;;
-;; This file is part of GCC.
-;;
-;; GCC is free software; you can redistribute it and/or modify it
-;; under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-;;
-;; GCC is distributed in the hope that it will be useful, but
-;; WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-;; General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING. If not, write to the Free
-;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-;; 02110-1301, USA. */
-
-;; Additional register numbers
-(define_constants
- [(VFPCC_REGNUM 95)]
-)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Pipeline description
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(define_automaton "vfp11")
-
-;; There are 3 pipelines in the VFP11 unit.
-;;
-;; - A 8-stage FMAC pipeline (7 execute + writeback) with forward from
-;; fourth stage for simple operations.
-;;
-;; - A 5-stage DS pipeline (4 execute + writeback) for divide/sqrt insns.
-;; These insns also uses first execute stage of FMAC pipeline.
-;;
-;; - A 4-stage LS pipeline (execute + 2 memory + writeback) with forward from
-;; second memory stage for loads.
-
-;; We do not model Write-After-Read hazards.
-;; We do not do write scheduling with the arm core, so it is only necessary
-;; to model the first stage of each pipeline
-;; ??? Need to model LS pipeline properly for load/store multiple?
-;; We do not model fmstat properly. This could be done by modeling pipelines
-;; properly and defining an absence set between a dummy fmstat unit and all
-;; other vfp units.
-
-(define_cpu_unit "fmac" "vfp11")
-
-(define_cpu_unit "ds" "vfp11")
-
-(define_cpu_unit "vfp_ls" "vfp11")
-
-(define_cpu_unit "fmstat" "vfp11")
-
-(exclusion_set "fmac,ds" "fmstat")
-
-;; The VFP "type" attributes differ from those used in the FPA model.
-;; ffarith Fast floating point insns, e.g. abs, neg, cpy, cmp.
-;; farith Most arithmetic insns.
-;; fmul Double precision multiply.
-;; fdivs Single precision sqrt or division.
-;; fdivd Double precision sqrt or division.
-;; f_flag fmstat operation
-;; f_load[sd] Floating point load from memory.
-;; f_store[sd] Floating point store to memory.
-;; f_2_r Transfer vfp to arm reg.
-;; r_2_f Transfer arm to vfp reg.
-;; f_cvt Convert floating<->integral
-
-(define_insn_reservation "vfp_ffarith" 4
- (and (eq_attr "generic_vfp" "yes")
- (eq_attr "type" "ffarith"))
- "fmac")
-
-(define_insn_reservation "vfp_farith" 8
- (and (eq_attr "generic_vfp" "yes")
- (eq_attr "type" "farith,f_cvt"))
- "fmac")
-
-(define_insn_reservation "vfp_fmul" 9
- (and (eq_attr "generic_vfp" "yes")
- (eq_attr "type" "fmul"))
- "fmac*2")
-
-(define_insn_reservation "vfp_fdivs" 19
- (and (eq_attr "generic_vfp" "yes")
- (eq_attr "type" "fdivs"))
- "ds*15")
-
-(define_insn_reservation "vfp_fdivd" 33
- (and (eq_attr "generic_vfp" "yes")
- (eq_attr "type" "fdivd"))
- "fmac+ds*29")
-
-;; Moves to/from arm regs also use the load/store pipeline.
-(define_insn_reservation "vfp_fload" 4
- (and (eq_attr "generic_vfp" "yes")
- (eq_attr "type" "f_loads,f_loadd,r_2_f"))
- "vfp_ls")
-
-(define_insn_reservation "vfp_fstore" 4
- (and (eq_attr "generic_vfp" "yes")
- (eq_attr "type" "f_stores,f_stored,f_2_r"))
- "vfp_ls")
-
-(define_insn_reservation "vfp_to_cpsr" 4
- (and (eq_attr "generic_vfp" "yes")
- (eq_attr "type" "f_flag"))
- "fmstat,vfp_ls*3")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Insn pattern
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; SImode moves
-;; ??? For now do not allow loading constants into vfp regs. This causes
-;; problems because small constants get converted into adds.
-(define_insn "*arm_movsi_vfp"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r ,m,*w,r,*w,*w, *Uv")
- (match_operand:SI 1 "general_operand" "rI,K,mi,r,r,*w,*w,*Uvi,*w"))]
- "TARGET_ARM && TARGET_VFP && TARGET_HARD_FLOAT
- && ( s_register_operand (operands[0], SImode)
- || s_register_operand (operands[1], SImode))"
- "@
- mov%?\\t%0, %1
- mvn%?\\t%0, #%B1
- ldr%?\\t%0, %1
- str%?\\t%1, %0
- fmsr%?\\t%0, %1\\t%@ int
- fmrs%?\\t%0, %1\\t%@ int
- fcpys%?\\t%0, %1\\t%@ int
- flds%?\\t%0, %1\\t%@ int
- fsts%?\\t%1, %0\\t%@ int"
- [(set_attr "predicable" "yes")
- (set_attr "type" "*,*,load1,store1,r_2_f,f_2_r,ffarith,f_loads,f_stores")
- (set_attr "pool_range" "*,*,4096,*,*,*,*,1020,*")
- (set_attr "neg_pool_range" "*,*,4084,*,*,*,*,1008,*")]
-)
-
-
-;; DImode moves
-
-(define_insn "*arm_movdi_vfp"
- [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r,m,w,r,w,w, Uv")
- (match_operand:DI 1 "di_operand" "rIK,mi,r,r,w,w,Uvi,w"))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP
- && ( register_operand (operands[0], DImode)
- || register_operand (operands[1], DImode))"
- "*
- switch (which_alternative)
- {
- case 0:
- return \"#\";
- case 1:
- case 2:
- return output_move_double (operands);
- case 3:
- return \"fmdrr%?\\t%P0, %Q1, %R1\\t%@ int\";
- case 4:
- return \"fmrrd%?\\t%Q0, %R0, %P1\\t%@ int\";
- case 5:
- return \"fcpyd%?\\t%P0, %P1\\t%@ int\";
- case 6:
- return \"fldd%?\\t%P0, %1\\t%@ int\";
- case 7:
- return \"fstd%?\\t%P1, %0\\t%@ int\";
- default:
- gcc_unreachable ();
- }
- "
- [(set_attr "type" "*,load2,store2,r_2_f,f_2_r,ffarith,f_loadd,f_stored")
- (set_attr "length" "8,8,8,4,4,4,4,4")
- (set_attr "pool_range" "*,1020,*,*,*,*,1020,*")
- (set_attr "neg_pool_range" "*,1008,*,*,*,*,1008,*")]
-)
-
-
-;; SFmode moves
-;; Disparage the w<->r cases because reloading an invalid address is
-;; preferable to loading the value via integer registers.
-
-(define_insn "*movsf_vfp"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=w,?r,w ,Uv,r ,m,w,r")
- (match_operand:SF 1 "general_operand" " ?r,w,UvE,w, mE,r,w,r"))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP
- && ( s_register_operand (operands[0], SFmode)
- || s_register_operand (operands[1], SFmode))"
- "@
- fmsr%?\\t%0, %1
- fmrs%?\\t%0, %1
- flds%?\\t%0, %1
- fsts%?\\t%1, %0
- ldr%?\\t%0, %1\\t%@ float
- str%?\\t%1, %0\\t%@ float
- fcpys%?\\t%0, %1
- mov%?\\t%0, %1\\t%@ float"
- [(set_attr "predicable" "yes")
- (set_attr "type" "r_2_f,f_2_r,ffarith,*,f_loads,f_stores,load1,store1")
- (set_attr "pool_range" "*,*,1020,*,4096,*,*,*")
- (set_attr "neg_pool_range" "*,*,1008,*,4080,*,*,*")]
-)
-
-
-;; DFmode moves
-
-(define_insn "*movdf_vfp"
- [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,r, m,w ,Uv,w,r")
- (match_operand:DF 1 "soft_df_operand" " ?r,w,mF,r,UvF,w, w,r"))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP
- && ( register_operand (operands[0], DFmode)
- || register_operand (operands[1], DFmode))"
- "*
- {
- switch (which_alternative)
- {
- case 0:
- return \"fmdrr%?\\t%P0, %Q1, %R1\";
- case 1:
- return \"fmrrd%?\\t%Q0, %R0, %P1\";
- case 2: case 3:
- return output_move_double (operands);
- case 4:
- return \"fldd%?\\t%P0, %1\";
- case 5:
- return \"fstd%?\\t%P1, %0\";
- case 6:
- return \"fcpyd%?\\t%P0, %P1\";
- case 7:
- return \"#\";
- default:
- gcc_unreachable ();
- }
- }
- "
- [(set_attr "type" "r_2_f,f_2_r,ffarith,*,load2,store2,f_loadd,f_stored")
- (set_attr "length" "4,4,8,8,4,4,4,8")
- (set_attr "pool_range" "*,*,1020,*,1020,*,*,*")
- (set_attr "neg_pool_range" "*,*,1008,*,1008,*,*,*")]
-)
-
-
-;; Conditional move patterns
-
-(define_insn "*movsfcc_vfp"
- [(set (match_operand:SF 0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
- (if_then_else:SF
- (match_operator 3 "arm_comparison_operator"
- [(match_operand 4 "cc_register" "") (const_int 0)])
- (match_operand:SF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
- (match_operand:SF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "@
- fcpys%D3\\t%0, %2
- fcpys%d3\\t%0, %1
- fcpys%D3\\t%0, %2\;fcpys%d3\\t%0, %1
- fmsr%D3\\t%0, %2
- fmsr%d3\\t%0, %1
- fmsr%D3\\t%0, %2\;fmsr%d3\\t%0, %1
- fmrs%D3\\t%0, %2
- fmrs%d3\\t%0, %1
- fmrs%D3\\t%0, %2\;fmrs%d3\\t%0, %1"
- [(set_attr "conds" "use")
- (set_attr "length" "4,4,8,4,4,8,4,4,8")
- (set_attr "type" "ffarith,ffarith,ffarith,r_2_f,r_2_f,r_2_f,f_2_r,f_2_r,f_2_r")]
-)
-
-(define_insn "*movdfcc_vfp"
- [(set (match_operand:DF 0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
- (if_then_else:DF
- (match_operator 3 "arm_comparison_operator"
- [(match_operand 4 "cc_register" "") (const_int 0)])
- (match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
- (match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "@
- fcpyd%D3\\t%P0, %P2
- fcpyd%d3\\t%P0, %P1
- fcpyd%D3\\t%P0, %P2\;fcpyd%d3\\t%P0, %P1
- fmdrr%D3\\t%P0, %Q2, %R2
- fmdrr%d3\\t%P0, %Q1, %R1
- fmdrr%D3\\t%P0, %Q2, %R2\;fmdrr%d3\\t%P0, %Q1, %R1
- fmrrd%D3\\t%Q0, %R0, %P2
- fmrrd%d3\\t%Q0, %R0, %P1
- fmrrd%D3\\t%Q0, %R0, %P2\;fmrrd%d3\\t%Q0, %R0, %P1"
- [(set_attr "conds" "use")
- (set_attr "length" "4,4,8,4,4,8,4,4,8")
- (set_attr "type" "ffarith,ffarith,ffarith,r_2_f,r_2_f,r_2_f,f_2_r,f_2_r,f_2_r")]
-)
-
-
-;; Sign manipulation functions
-
-(define_insn "*abssf2_vfp"
- [(set (match_operand:SF 0 "s_register_operand" "=w")
- (abs:SF (match_operand:SF 1 "s_register_operand" "w")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "fabss%?\\t%0, %1"
- [(set_attr "predicable" "yes")
- (set_attr "type" "ffarith")]
-)
-
-(define_insn "*absdf2_vfp"
- [(set (match_operand:DF 0 "s_register_operand" "=w")
- (abs:DF (match_operand:DF 1 "s_register_operand" "w")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "fabsd%?\\t%P0, %P1"
- [(set_attr "predicable" "yes")
- (set_attr "type" "ffarith")]
-)
-
-(define_insn "*negsf2_vfp"
- [(set (match_operand:SF 0 "s_register_operand" "=w,?r")
- (neg:SF (match_operand:SF 1 "s_register_operand" "w,r")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "@
- fnegs%?\\t%0, %1
- eor%?\\t%0, %1, #-2147483648"
- [(set_attr "predicable" "yes")
- (set_attr "type" "ffarith")]
-)
-
-(define_insn_and_split "*negdf2_vfp"
- [(set (match_operand:DF 0 "s_register_operand" "=w,?r,?r")
- (neg:DF (match_operand:DF 1 "s_register_operand" "w,0,r")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "@
- fnegd%?\\t%P0, %P1
- #
- #"
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP && reload_completed
- && arm_general_register_operand (operands[0], DFmode)"
- [(set (match_dup 0) (match_dup 1))]
- "
- if (REGNO (operands[0]) == REGNO (operands[1]))
- {
- operands[0] = gen_highpart (SImode, operands[0]);
- operands[1] = gen_rtx_XOR (SImode, operands[0], GEN_INT (0x80000000));
- }
- else
- {
- rtx in_hi, in_lo, out_hi, out_lo;
-
- in_hi = gen_rtx_XOR (SImode, gen_highpart (SImode, operands[1]),
- GEN_INT (0x80000000));
- in_lo = gen_lowpart (SImode, operands[1]);
- out_hi = gen_highpart (SImode, operands[0]);
- out_lo = gen_lowpart (SImode, operands[0]);
-
- if (REGNO (in_lo) == REGNO (out_hi))
- {
- emit_insn (gen_rtx_SET (SImode, out_lo, in_lo));
- operands[0] = out_hi;
- operands[1] = in_hi;
- }
- else
- {
- emit_insn (gen_rtx_SET (SImode, out_hi, in_hi));
- operands[0] = out_lo;
- operands[1] = in_lo;
- }
- }
- "
- [(set_attr "predicable" "yes")
- (set_attr "length" "4,4,8")
- (set_attr "type" "ffarith")]
-)
-
-
-;; Arithmetic insns
-
-(define_insn "*addsf3_vfp"
- [(set (match_operand:SF 0 "s_register_operand" "=w")
- (plus:SF (match_operand:SF 1 "s_register_operand" "w")
- (match_operand:SF 2 "s_register_operand" "w")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "fadds%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")
- (set_attr "type" "farith")]
-)
-
-(define_insn "*adddf3_vfp"
- [(set (match_operand:DF 0 "s_register_operand" "=w")
- (plus:DF (match_operand:DF 1 "s_register_operand" "w")
- (match_operand:DF 2 "s_register_operand" "w")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "faddd%?\\t%P0, %P1, %P2"
- [(set_attr "predicable" "yes")
- (set_attr "type" "farith")]
-)
-
-
-(define_insn "*subsf3_vfp"
- [(set (match_operand:SF 0 "s_register_operand" "=w")
- (minus:SF (match_operand:SF 1 "s_register_operand" "w")
- (match_operand:SF 2 "s_register_operand" "w")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "fsubs%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")
- (set_attr "type" "farith")]
-)
-
-(define_insn "*subdf3_vfp"
- [(set (match_operand:DF 0 "s_register_operand" "=w")
- (minus:DF (match_operand:DF 1 "s_register_operand" "w")
- (match_operand:DF 2 "s_register_operand" "w")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "fsubd%?\\t%P0, %P1, %P2"
- [(set_attr "predicable" "yes")
- (set_attr "type" "farith")]
-)
-
-
-;; Division insns
-
-(define_insn "*divsf3_vfp"
- [(set (match_operand:SF 0 "s_register_operand" "+w")
- (div:SF (match_operand:SF 1 "s_register_operand" "w")
- (match_operand:SF 2 "s_register_operand" "w")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "fdivs%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")
- (set_attr "type" "fdivs")]
-)
-
-(define_insn "*divdf3_vfp"
- [(set (match_operand:DF 0 "s_register_operand" "+w")
- (div:DF (match_operand:DF 1 "s_register_operand" "w")
- (match_operand:DF 2 "s_register_operand" "w")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "fdivd%?\\t%P0, %P1, %P2"
- [(set_attr "predicable" "yes")
- (set_attr "type" "fdivd")]
-)
-
-
-;; Multiplication insns
-
-(define_insn "*mulsf3_vfp"
- [(set (match_operand:SF 0 "s_register_operand" "+w")
- (mult:SF (match_operand:SF 1 "s_register_operand" "w")
- (match_operand:SF 2 "s_register_operand" "w")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "fmuls%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")
- (set_attr "type" "farith")]
-)
-
-(define_insn "*muldf3_vfp"
- [(set (match_operand:DF 0 "s_register_operand" "+w")
- (mult:DF (match_operand:DF 1 "s_register_operand" "w")
- (match_operand:DF 2 "s_register_operand" "w")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "fmuld%?\\t%P0, %P1, %P2"
- [(set_attr "predicable" "yes")
- (set_attr "type" "fmul")]
-)
-
-
-(define_insn "*mulsf3negsf_vfp"
- [(set (match_operand:SF 0 "s_register_operand" "+w")
- (mult:SF (neg:SF (match_operand:SF 1 "s_register_operand" "w"))
- (match_operand:SF 2 "s_register_operand" "w")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "fnmuls%?\\t%0, %1, %2"
- [(set_attr "predicable" "yes")
- (set_attr "type" "farith")]
-)
-
-(define_insn "*muldf3negdf_vfp"
- [(set (match_operand:DF 0 "s_register_operand" "+w")
- (mult:DF (neg:DF (match_operand:DF 1 "s_register_operand" "w"))
- (match_operand:DF 2 "s_register_operand" "w")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "fnmuld%?\\t%P0, %P1, %P2"
- [(set_attr "predicable" "yes")
- (set_attr "type" "fmul")]
-)
-
-
-;; Multiply-accumulate insns
-
-;; 0 = 1 * 2 + 0
-(define_insn "*mulsf3addsf_vfp"
- [(set (match_operand:SF 0 "s_register_operand" "=w")
- (plus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "w")
- (match_operand:SF 3 "s_register_operand" "w"))
- (match_operand:SF 1 "s_register_operand" "0")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "fmacs%?\\t%0, %2, %3"
- [(set_attr "predicable" "yes")
- (set_attr "type" "farith")]
-)
-
-(define_insn "*muldf3adddf_vfp"
- [(set (match_operand:DF 0 "s_register_operand" "=w")
- (plus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
- (match_operand:DF 3 "s_register_operand" "w"))
- (match_operand:DF 1 "s_register_operand" "0")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "fmacd%?\\t%P0, %P2, %P3"
- [(set_attr "predicable" "yes")
- (set_attr "type" "fmul")]
-)
-
-;; 0 = 1 * 2 - 0
-(define_insn "*mulsf3subsf_vfp"
- [(set (match_operand:SF 0 "s_register_operand" "=w")
- (minus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "w")
- (match_operand:SF 3 "s_register_operand" "w"))
- (match_operand:SF 1 "s_register_operand" "0")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "fmscs%?\\t%0, %2, %3"
- [(set_attr "predicable" "yes")
- (set_attr "type" "farith")]
-)
-
-(define_insn "*muldf3subdf_vfp"
- [(set (match_operand:DF 0 "s_register_operand" "=w")
- (minus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
- (match_operand:DF 3 "s_register_operand" "w"))
- (match_operand:DF 1 "s_register_operand" "0")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "fmscd%?\\t%P0, %P2, %P3"
- [(set_attr "predicable" "yes")
- (set_attr "type" "fmul")]
-)
-
-;; 0 = -(1 * 2) + 0
-(define_insn "*mulsf3negsfaddsf_vfp"
- [(set (match_operand:SF 0 "s_register_operand" "=w")
- (minus:SF (match_operand:SF 1 "s_register_operand" "0")
- (mult:SF (match_operand:SF 2 "s_register_operand" "w")
- (match_operand:SF 3 "s_register_operand" "w"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "fnmacs%?\\t%0, %2, %3"
- [(set_attr "predicable" "yes")
- (set_attr "type" "farith")]
-)
-
-(define_insn "*fmuldf3negdfadddf_vfp"
- [(set (match_operand:DF 0 "s_register_operand" "=w")
- (minus:DF (match_operand:DF 1 "s_register_operand" "0")
- (mult:DF (match_operand:DF 2 "s_register_operand" "w")
- (match_operand:DF 3 "s_register_operand" "w"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "fnmacd%?\\t%P0, %P2, %P3"
- [(set_attr "predicable" "yes")
- (set_attr "type" "fmul")]
-)
-
-
-;; 0 = -(1 * 2) - 0
-(define_insn "*mulsf3negsfsubsf_vfp"
- [(set (match_operand:SF 0 "s_register_operand" "=w")
- (minus:SF (mult:SF
- (neg:SF (match_operand:SF 2 "s_register_operand" "w"))
- (match_operand:SF 3 "s_register_operand" "w"))
- (match_operand:SF 1 "s_register_operand" "0")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "fnmscs%?\\t%0, %2, %3"
- [(set_attr "predicable" "yes")
- (set_attr "type" "farith")]
-)
-
-(define_insn "*muldf3negdfsubdf_vfp"
- [(set (match_operand:DF 0 "s_register_operand" "=w")
- (minus:DF (mult:DF
- (neg:DF (match_operand:DF 2 "s_register_operand" "w"))
- (match_operand:DF 3 "s_register_operand" "w"))
- (match_operand:DF 1 "s_register_operand" "0")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "fnmscd%?\\t%P0, %P2, %P3"
- [(set_attr "predicable" "yes")
- (set_attr "type" "fmul")]
-)
-
-
-;; Conversion routines
-
-(define_insn "*extendsfdf2_vfp"
- [(set (match_operand:DF 0 "s_register_operand" "=w")
- (float_extend:DF (match_operand:SF 1 "s_register_operand" "w")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "fcvtds%?\\t%P0, %1"
- [(set_attr "predicable" "yes")
- (set_attr "type" "f_cvt")]
-)
-
-(define_insn "*truncdfsf2_vfp"
- [(set (match_operand:SF 0 "s_register_operand" "=w")
- (float_truncate:SF (match_operand:DF 1 "s_register_operand" "w")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "fcvtsd%?\\t%0, %P1"
- [(set_attr "predicable" "yes")
- (set_attr "type" "f_cvt")]
-)
-
-(define_insn "*truncsisf2_vfp"
- [(set (match_operand:SI 0 "s_register_operand" "=w")
- (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "w"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "ftosizs%?\\t%0, %1"
- [(set_attr "predicable" "yes")
- (set_attr "type" "f_cvt")]
-)
-
-(define_insn "*truncsidf2_vfp"
- [(set (match_operand:SI 0 "s_register_operand" "=w")
- (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "w"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "ftosizd%?\\t%0, %P1"
- [(set_attr "predicable" "yes")
- (set_attr "type" "f_cvt")]
-)
-
-
-(define_insn "fixuns_truncsfsi2"
- [(set (match_operand:SI 0 "s_register_operand" "=w")
- (unsigned_fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "w"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "ftouizs%?\\t%0, %1"
- [(set_attr "predicable" "yes")
- (set_attr "type" "f_cvt")]
-)
-
-(define_insn "fixuns_truncdfsi2"
- [(set (match_operand:SI 0 "s_register_operand" "=w")
- (unsigned_fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "w"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "ftouizd%?\\t%0, %P1"
- [(set_attr "predicable" "yes")
- (set_attr "type" "f_cvt")]
-)
-
-
-(define_insn "*floatsisf2_vfp"
- [(set (match_operand:SF 0 "s_register_operand" "=w")
- (float:SF (match_operand:SI 1 "s_register_operand" "w")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "fsitos%?\\t%0, %1"
- [(set_attr "predicable" "yes")
- (set_attr "type" "f_cvt")]
-)
-
-(define_insn "*floatsidf2_vfp"
- [(set (match_operand:DF 0 "s_register_operand" "=w")
- (float:DF (match_operand:SI 1 "s_register_operand" "w")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "fsitod%?\\t%P0, %1"
- [(set_attr "predicable" "yes")
- (set_attr "type" "f_cvt")]
-)
-
-
-(define_insn "floatunssisf2"
- [(set (match_operand:SF 0 "s_register_operand" "=w")
- (unsigned_float:SF (match_operand:SI 1 "s_register_operand" "w")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "fuitos%?\\t%0, %1"
- [(set_attr "predicable" "yes")
- (set_attr "type" "f_cvt")]
-)
-
-(define_insn "floatunssidf2"
- [(set (match_operand:DF 0 "s_register_operand" "=w")
- (unsigned_float:DF (match_operand:SI 1 "s_register_operand" "w")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "fuitod%?\\t%P0, %1"
- [(set_attr "predicable" "yes")
- (set_attr "type" "f_cvt")]
-)
-
-
-;; Sqrt insns.
-
-(define_insn "*sqrtsf2_vfp"
- [(set (match_operand:SF 0 "s_register_operand" "=w")
- (sqrt:SF (match_operand:SF 1 "s_register_operand" "w")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "fsqrts%?\\t%0, %1"
- [(set_attr "predicable" "yes")
- (set_attr "type" "fdivs")]
-)
-
-(define_insn "*sqrtdf2_vfp"
- [(set (match_operand:DF 0 "s_register_operand" "=w")
- (sqrt:DF (match_operand:DF 1 "s_register_operand" "w")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "fsqrtd%?\\t%P0, %P1"
- [(set_attr "predicable" "yes")
- (set_attr "type" "fdivd")]
-)
-
-
-;; Patterns to split/copy vfp condition flags.
-
-(define_insn "*movcc_vfp"
- [(set (reg CC_REGNUM)
- (reg VFPCC_REGNUM))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "fmstat%?"
- [(set_attr "conds" "set")
- (set_attr "type" "f_flag")]
-)
-
-(define_insn_and_split "*cmpsf_split_vfp"
- [(set (reg:CCFP CC_REGNUM)
- (compare:CCFP (match_operand:SF 0 "s_register_operand" "w")
- (match_operand:SF 1 "vfp_compare_operand" "wG")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "#"
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- [(set (reg:CCFP VFPCC_REGNUM)
- (compare:CCFP (match_dup 0)
- (match_dup 1)))
- (set (reg:CCFP CC_REGNUM)
- (reg:CCFP VFPCC_REGNUM))]
- ""
-)
-
-(define_insn_and_split "*cmpsf_trap_split_vfp"
- [(set (reg:CCFPE CC_REGNUM)
- (compare:CCFPE (match_operand:SF 0 "s_register_operand" "w")
- (match_operand:SF 1 "vfp_compare_operand" "wG")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "#"
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- [(set (reg:CCFPE VFPCC_REGNUM)
- (compare:CCFPE (match_dup 0)
- (match_dup 1)))
- (set (reg:CCFPE CC_REGNUM)
- (reg:CCFPE VFPCC_REGNUM))]
- ""
-)
-
-(define_insn_and_split "*cmpdf_split_vfp"
- [(set (reg:CCFP CC_REGNUM)
- (compare:CCFP (match_operand:DF 0 "s_register_operand" "w")
- (match_operand:DF 1 "vfp_compare_operand" "wG")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "#"
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- [(set (reg:CCFP VFPCC_REGNUM)
- (compare:CCFP (match_dup 0)
- (match_dup 1)))
- (set (reg:CCFP CC_REGNUM)
- (reg:CCFPE VFPCC_REGNUM))]
- ""
-)
-
-(define_insn_and_split "*cmpdf_trap_split_vfp"
- [(set (reg:CCFPE CC_REGNUM)
- (compare:CCFPE (match_operand:DF 0 "s_register_operand" "w")
- (match_operand:DF 1 "vfp_compare_operand" "wG")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "#"
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- [(set (reg:CCFPE VFPCC_REGNUM)
- (compare:CCFPE (match_dup 0)
- (match_dup 1)))
- (set (reg:CCFPE CC_REGNUM)
- (reg:CCFPE VFPCC_REGNUM))]
- ""
-)
-
-
-;; Comparison patterns
-
-(define_insn "*cmpsf_vfp"
- [(set (reg:CCFP VFPCC_REGNUM)
- (compare:CCFP (match_operand:SF 0 "s_register_operand" "w,w")
- (match_operand:SF 1 "vfp_compare_operand" "w,G")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "@
- fcmps%?\\t%0, %1
- fcmpzs%?\\t%0"
- [(set_attr "predicable" "yes")
- (set_attr "type" "ffarith")]
-)
-
-(define_insn "*cmpsf_trap_vfp"
- [(set (reg:CCFPE VFPCC_REGNUM)
- (compare:CCFPE (match_operand:SF 0 "s_register_operand" "w,w")
- (match_operand:SF 1 "vfp_compare_operand" "w,G")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "@
- fcmpes%?\\t%0, %1
- fcmpezs%?\\t%0"
- [(set_attr "predicable" "yes")
- (set_attr "type" "ffarith")]
-)
-
-(define_insn "*cmpdf_vfp"
- [(set (reg:CCFP VFPCC_REGNUM)
- (compare:CCFP (match_operand:DF 0 "s_register_operand" "w,w")
- (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "@
- fcmpd%?\\t%P0, %P1
- fcmpzd%?\\t%P0"
- [(set_attr "predicable" "yes")
- (set_attr "type" "ffarith")]
-)
-
-(define_insn "*cmpdf_trap_vfp"
- [(set (reg:CCFPE VFPCC_REGNUM)
- (compare:CCFPE (match_operand:DF 0 "s_register_operand" "w,w")
- (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "@
- fcmped%?\\t%P0, %P1
- fcmpezd%?\\t%P0"
- [(set_attr "predicable" "yes")
- (set_attr "type" "ffarith")]
-)
-
-
-;; Store multiple insn used in function prologue.
-
-(define_insn "*push_multi_vfp"
- [(match_parallel 2 "multi_register_push"
- [(set (match_operand:BLK 0 "memory_operand" "=m")
- (unspec:BLK [(match_operand:DF 1 "s_register_operand" "w")]
- UNSPEC_PUSH_MULT))])]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
- "* return vfp_output_fstmx (operands);"
- [(set_attr "type" "f_stored")]
-)
-
-
-;; Unimplemented insns:
-;; fldm*
-;; fstm*
-;; fmdhr et al (VFPv1)
-;; Support for xD (single precision only) variants.
-;; fmrrs, fmsrr
diff --git a/gcc-4.2.1/gcc/config/arm/vxworks.h b/gcc-4.2.1/gcc/config/arm/vxworks.h
deleted file mode 100644
index 319c1e842..000000000
--- a/gcc-4.2.1/gcc/config/arm/vxworks.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* Definitions of target machine for GCC,
- for ARM with targetting the VXWorks run time environment.
- Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc.
-
- Contributed by: Mike Stump <mrs@wrs.com>
- Brought up to date by CodeSourcery, LLC.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
-
-
-#define TARGET_OS_CPP_BUILTINS() \
- do { \
- builtin_define ("__vxworks"); \
- if (TARGET_BIG_END) \
- builtin_define ("ARMEB"); \
- else \
- builtin_define ("ARMEL"); \
- \
- if (arm_is_xscale) \
- builtin_define ("CPU=XSCALE"); \
- else if (arm_arch5) \
- builtin_define ("CPU=ARMARCH5"); \
- else if (arm_arch4) \
- { \
- if (thumb_code) \
- builtin_define ("CPU=ARMARCH4_T"); \
- else \
- builtin_define ("CPU=ARMARCH4"); \
- } \
- } while (0)
-
-#undef CC1_SPEC
-#define CC1_SPEC \
-"%{t4: -mlittle-endian -march=armv4 ; \
- t4be: -mbig-endian -march=armv4 ; \
- t4t: -mthumb -mthumb-interwork -mlittle-endian -march=armv4t ; \
- t4tbe: -mthumb -mthumb-interwork -mbig-endian -march=armv4t ; \
- t5: -mlittle-endian -march=armv5 ; \
- t5be: -mbig-endian -march=armv5 ; \
- t5t: -mthumb -mthumb-interwork -mlittle-endian -march=armv5 ; \
- t5tbe: -mthumb -mthumb-interwork -mbig-endian -march=armv5 ; \
- txscale: -mlittle-endian -mcpu=xscale ; \
- txscalebe: -mbig-endian -mcpu=xscale ; \
- : -march=armv4}"
-
-/* The -Q options from svr4.h aren't understood and must be removed. */
-#undef ASM_SPEC
-#define ASM_SPEC \
- "%{v:-V} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*}"
-
-/* VxWorks does all the library stuff itself. */
-#undef LIB_SPEC
-#define LIB_SPEC ""
-
-/* VxWorks uses object files, not loadable images. make linker just
- combine objects. */
-#undef LINK_SPEC
-#define LINK_SPEC "-r"
-
-/* VxWorks provides the functionality of crt0.o and friends itself. */
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC ""
-
-#undef ENDFILE_SPEC
-#define ENDFILE_SPEC ""
-
-#undef TARGET_VERSION
-#define TARGET_VERSION fputs (" (ARM/VxWorks)", stderr);
-
-/* There is no default multilib. */
-#undef MULTILIB_DEFAULTS
-
-#undef ASM_FILE_START
-#define ASM_FILE_START(STREAM) \
- do \
- { \
- fprintf (STREAM, "%s Generated by GCC %s for ARM/VxWorks\n", \
- ASM_COMMENT_START, version_string); \
- } \
- while (0)
diff --git a/gcc-4.2.1/gcc/config/arm/wince-pe.h b/gcc-4.2.1/gcc/config/arm/wince-pe.h
deleted file mode 100644
index 530340f9d..000000000
--- a/gcc-4.2.1/gcc/config/arm/wince-pe.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Definitions of target machine for GNU compiler, for ARM with WINCE-PE obj format.
- Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
- Contributed by Nick Clifton <nickc@redhat.com>
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_NOP_FUN_DLLIMPORT)
-
-#undef MULTILIB_DEFAULTS
-#define MULTILIB_DEFAULTS \
- { "marm", "mlittle-endian", "msoft-float", "mno-thumb-interwork" }
diff --git a/gcc-4.2.1/gcc/config/arm/xscale-coff.h b/gcc-4.2.1/gcc/config/arm/xscale-coff.h
deleted file mode 100644
index e27594348..000000000
--- a/gcc-4.2.1/gcc/config/arm/xscale-coff.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Definitions for XScale systems using COFF
- Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
- Contributed by Catherine Moore <clm@cygnus.com>
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
- MA 02110-1301, USA. */
-
-/* Run-time Target Specification. */
-#undef SUBTARGET_CPU_DEFAULT
-#define SUBTARGET_CPU_DEFAULT TARGET_CPU_xscale
-
-#undef SUBTARGET_EXTRA_ASM_SPEC
-#define SUBTARGET_EXTRA_ASM_SPEC "%{!mcpu=*:-mcpu=xscale}"
-
-#undef MULTILIB_DEFAULTS
-#define MULTILIB_DEFAULTS \
- { "mlittle-endian", "mno-thumb-interwork", "marm" }
-
-#undef TARGET_VERSION
-#define TARGET_VERSION fputs (" (XScale/COFF)", stderr);
diff --git a/gcc-4.2.1/gcc/config/arm/xscale-elf.h b/gcc-4.2.1/gcc/config/arm/xscale-elf.h
deleted file mode 100644
index be7be087b..000000000
--- a/gcc-4.2.1/gcc/config/arm/xscale-elf.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Definitions for XScale architectures using ELF
- Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
- Contributed by Catherine Moore <clm@cygnus.com>
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* Run-time Target Specification. */
-#ifndef TARGET_VERSION
-#define TARGET_VERSION fputs (" (XScale/ELF non-Linux)", stderr);
-#endif
-
-#ifndef SUBTARGET_CPU_DEFAULT
-#define SUBTARGET_CPU_DEFAULT TARGET_CPU_xscale
-#endif
-
-/* Note - there are three possible -mfpu= arguments that can be passed to
- the assembler:
-
- -mfpu=softvfp This is the default. It indicates thats doubles are
- stored in a format compatible with the VFP
- specification. This is the newer double format, whereby
- the endian-ness of the doubles matches the endian-ness
- of the memory architecture.
-
- -mfpu=fpa This is when -mhard-float is specified.
- [It is not known if any XScale's have been made with
- hardware floating point support, but nevertheless this
- is what happens].
-
- -mfpu=softfpa This is when -msoft-float is specified.
- This is the normal behavior of other arm configurations,
- which for backwards compatibility purposes default to
- supporting the old FPA format which was always big
- endian, regardless of the endian-ness of the memory
- system. */
-
-#define SUBTARGET_EXTRA_ASM_SPEC "%{!mcpu=*:-mcpu=xscale} \
- %{mhard-float:-mfpu=fpa} \
- %{!mhard-float: %{msoft-float:-mfpu=softfpa;:-mfpu=softvfp}}"
-
-#ifndef MULTILIB_DEFAULTS
-#define MULTILIB_DEFAULTS \
- { "mlittle-endian", "mno-thumb-interwork", "marm", "msoft-float" }
-#endif