| /* Definitions for GCC. Part of the machine description for CRIS. |
| Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. |
| Contributed by Axis Communications. Written by Hans-Peter Nilsson. |
| |
| This file is part of GCC. |
| |
| GCC is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2, or (at your option) |
| any later version. |
| |
| GCC is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GCC; see the file COPYING. If not, write to |
| the Free Software Foundation, 59 Temple Place - Suite 330, |
| Boston, MA 02111-1307, USA. */ |
| |
| /* After the first "Node:" comment comes all preprocessor directives and |
| attached declarations described in the info files, the "Using and |
| Porting GCC" manual (uapgcc), in the same order as found in the "Target |
| macros" section in the gcc-2.9x CVS edition of 2000-03-17. FIXME: Not |
| really, but needs an update anyway. |
| |
| There is no generic copy-of-uapgcc comment, you'll have to see uapgcc |
| for that. If applicable, there is a CRIS-specific comment. The order |
| of macro definitions follow the order in the manual. Every section in |
| the manual (node in the info pages) has an introductory `Node: |
| <subchapter>' comment. If no macros are defined for a section, only |
| the section-comment is present. */ |
| |
| /* Note that other header files (e.g. config/elfos.h, config/linux.h, |
| config/cris/linux.h and config/cris/aout.h) are responsible for lots of |
| settings not repeated below. This file contains general CRIS |
| definitions and definitions for the cris-*-elf subtarget. */ |
| |
| /* Replacement for REG_P since it does not match SUBREGs. Happens for |
| testcase Axis-20000320 with gcc-2.9x. */ |
| #define REG_S_P(x) \ |
| (REG_P (x) || (GET_CODE (x) == SUBREG && REG_P (XEXP (x, 0)))) |
| |
| /* Last register in main register bank r0..r15. */ |
| #define CRIS_LAST_GENERAL_REGISTER 15 |
| |
| /* Descriptions of registers used for arguments. */ |
| #define CRIS_FIRST_ARG_REG 10 |
| #define CRIS_MAX_ARGS_IN_REGS 4 |
| |
| /* Other convenience definitions. */ |
| #define CRIS_PC_REGNUM 15 |
| #define CRIS_SRP_REGNUM 16 |
| |
| /* Most of the time, we need the index into the register-names array. |
| When passing debug-info, we need the real register number. */ |
| #define CRIS_CANONICAL_SRP_REGNUM (16 + 11) |
| #define CRIS_CANONICAL_MOF_REGNUM (16 + 7) |
| |
| /* When generating PIC, these suffixes are added to the names of non-local |
| functions when being output. Contrary to other ports, we have offsets |
| relative to the GOT, not the PC. We might implement PC-relative PLT |
| semantics later for the general case; they are used in some cases right |
| now, such as MI thunks. */ |
| #define CRIS_GOTPLT_SUFFIX ":GOTPLT" |
| #define CRIS_PLT_GOTOFFSET_SUFFIX ":PLTG" |
| #define CRIS_PLT_PCOFFSET_SUFFIX ":PLT" |
| |
| /* If you tweak this, don't forget to check cris_expand_builtin_va_arg. */ |
| #define CRIS_FUNCTION_ARG_SIZE(MODE, TYPE) \ |
| ((MODE) != BLKmode ? GET_MODE_SIZE (MODE) \ |
| : (unsigned) int_size_in_bytes (TYPE)) |
| |
| /* Check for max allowed stackframe. A "const char *" to be parsed. */ |
| extern const char *cris_max_stackframe_str; |
| |
| /* Which CPU version this is. A "const char *" to be parsed. */ |
| extern const char *cris_cpu_str; |
| |
| /* Which CPU version this is. The parsed and adjusted cris_cpu_str. */ |
| extern int cris_cpu_version; |
| |
| /* Which CPU version to tune for. A "const char *" to be parsed. */ |
| extern const char *cris_tune_str; |
| |
| /* The argument to "-melinux-stacksize=". We don't parse it currently; |
| it's just passed on to the linker. We might want to do something |
| here someday. */ |
| extern const char *cris_elinux_stacksize_str; |
| |
| /* Changing the order used to be necessary to put the fourth __make_dp |
| argument (a DImode parameter) in registers, to fit with the libfunc |
| parameter passing scheme used for intrinsic functions. FIXME: Check |
| performance and maybe remove definition from TARGET_LIBGCC2_CFLAGS now |
| that it isn't strictly necessary. We used to do this through |
| TARGET_LIBGCC2_CFLAGS, but that became increasingly difficult as the |
| parenthesis (that needed quoting) travels through several layers of |
| make and shell invocations. */ |
| #ifdef IN_LIBGCC2 |
| #define __make_dp(a,b,c,d) __cris_make_dp(d,a,b,c) |
| #endif |
| |
| |
| /* Node: Driver */ |
| |
| /* When using make with defaults.mak for Sun this will handily remove |
| any "-target sun*" switches. */ |
| /* We need to override any previous definitions (linux.h) */ |
| #undef WORD_SWITCH_TAKES_ARG |
| #define WORD_SWITCH_TAKES_ARG(STR) \ |
| (DEFAULT_WORD_SWITCH_TAKES_ARG (STR) \ |
| || !strcmp (STR, "target")) |
| |
| /* Also provide canonical vN definitions when user specifies an alias. |
| Note that -melf overrides -maout. */ |
| |
| #define CPP_SPEC \ |
| "%{mtune=*:-D__tune_%* %{mtune=v*:-D__CRIS_arch_tune=%*}}\ |
| %{mtune=etrax4:-D__tune_v3 -D__CRIS_arch_tune=3}\ |
| %{mtune=etrax100:-D__tune_v8 -D__CRIS_arch_tune=8}\ |
| %{mtune=svinto:-D__tune_v8 -D__CRIS_arch_tune=8}\ |
| %{mtune=etrax100lx:-D__tune_v10 -D__CRIS_arch_tune=10}\ |
| %{mtune=ng:-D__tune_v10 -D__CRIS_arch_tune=10}\ |
| %{mcpu=*:-D__arch_%* %{mcpu=v*:-D__CRIS_arch_version=%*}}\ |
| %{mcpu=etrax4:-D__arch_v3 -D__CRIS_arch_version=3}\ |
| %{mcpu=etrax100:-D__arch_v8 -D__CRIS_arch_version=8}\ |
| %{mcpu=svinto:-D__arch_v8 -D__CRIS_arch_version=8}\ |
| %{mcpu=etrax100lx:-D__arch_v10 -D__CRIS_arch_version=10}\ |
| %{mcpu=ng:-D__arch_v10 -D__CRIS_arch_version=10}\ |
| %{march=*:-D__arch_%* %{march=v*:-D__CRIS_arch_version=%*}}\ |
| %{march=etrax4:-D__arch_v3 -D__CRIS_arch_version=3}\ |
| %{march=etrax100:-D__arch_v8 -D__CRIS_arch_version=8}\ |
| %{march=svinto:-D__arch_v8 -D__CRIS_arch_version=8}\ |
| %{march=etrax100lx:-D__arch_v10 -D__CRIS_arch_version=10}\ |
| %{march=ng:-D__arch_v10 -D__CRIS_arch_version=10}\ |
| %{metrax100:-D__arch__v8 -D__CRIS_arch_version=8}\ |
| %{metrax4:-D__arch__v3 -D__CRIS_arch_version=3}\ |
| %(cpp_subtarget)" |
| |
| /* For the cris-*-elf subtarget. */ |
| #define CRIS_CPP_SUBTARGET_SPEC \ |
| "%{mbest-lib-options:\ |
| %{!moverride-best-lib-options:\ |
| %{!march=*:%{!metrax*:%{!mcpu=*:-D__tune_v10 -D__CRIS_arch_tune=10}}}}}" |
| |
| /* Remove those Sun-make "target" switches. */ |
| /* Override previous definitions (linux.h). */ |
| #undef CC1_SPEC |
| #define CC1_SPEC \ |
| "%{target*:}\ |
| %{metrax4:-march=v3}\ |
| %{metrax100:-march=v8}\ |
| %(cc1_subtarget)" |
| |
| /* For the cris-*-elf subtarget. */ |
| #define CRIS_CC1_SUBTARGET_SPEC \ |
| "-melf\ |
| %{mbest-lib-options:\ |
| %{!moverride-best-lib-options:\ |
| %{!march=*:%{!mcpu=*:-mtune=v10 -D__CRIS_arch_tune=10}}\ |
| %{!finhibit-size-directive:\ |
| %{!fno-function-sections: -ffunction-sections}\ |
| %{!fno-data-sections: -fdata-sections}}}}" |
| |
| /* This adds to CC1_SPEC. When bugs are removed from -fvtable-gc |
| (-fforce-addr causes invalid .vtable_entry asm in tinfo.cc and |
| nothing at all works in GCC 3.0-pre), add this line: |
| "%{mbest-lib-options:%{!moverride-best-lib-options:\ |
| %{!melinux:%{!maout|melf:%{!fno-vtable-gc:-fvtable-gc}}}}}". */ |
| #define CC1PLUS_SPEC "" |
| |
| #ifdef HAVE_AS_MUL_BUG_ABORT_OPTION |
| #define MAYBE_AS_NO_MUL_BUG_ABORT \ |
| "%{mno-mul-bug-workaround:-no-mul-bug-abort} " |
| #else |
| #define MAYBE_AS_NO_MUL_BUG_ABORT |
| #endif |
| |
| /* Override previous definitions (linux.h). */ |
| #undef ASM_SPEC |
| #define ASM_SPEC \ |
| MAYBE_AS_NO_MUL_BUG_ABORT \ |
| "%{v:-v}\ |
| %(asm_subtarget)" |
| |
| /* For the cris-*-elf subtarget. */ |
| #define CRIS_ASM_SUBTARGET_SPEC "--em=criself" |
| |
| /* FIXME: We should propagate the -melf option to make the criself |
| "emulation" unless a linker script is provided (-T*), but I don't know |
| how to do that if either of -Ttext, -Tdata or -Tbss is given but no |
| linker script, as is usually the case. Leave it to the user for the |
| time being. |
| |
| Note that -melf overrides -maout except that a.out-compiled libraries |
| are linked in (multilibbing). The somewhat cryptic -rpath-link pair is |
| to avoid *only* picking up the linux multilib subdir from the "-B./" |
| option during build, while still giving it preference. We'd need some |
| %s-variant that checked for existence of some specific file. */ |
| /* Override previous definitions (svr4.h). */ |
| #undef LINK_SPEC |
| #define LINK_SPEC \ |
| "%{v:--verbose}\ |
| %(link_subtarget)" |
| |
| /* For the cris-*-elf subtarget. */ |
| #define CRIS_LINK_SUBTARGET_SPEC \ |
| "-mcriself\ |
| %{sim2:%{!T*:-Tdata 0x4000000 -Tbss 0x8000000}}\ |
| %{!r:%{O2|O3: --gc-sections}}" |
| |
| /* Which library to get. The only difference from the default is to get |
| libsc.a if -sim is given to the driver. Repeat -lc -lsysX |
| {X=sim,linux}, because libsysX needs (at least) errno from libc, and |
| then we want to resolve new unknowns in libc against libsysX, not |
| libnosys. */ |
| /* Override previous definitions (linux.h). */ |
| #undef LIB_SPEC |
| #define LIB_SPEC \ |
| "%{sim*:-lc -lsyssim -lc -lsyssim}\ |
| %{!sim*:%{g*:-lg}\ |
| %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} -lbsp}\ |
| -lnosys" |
| |
| /* Linker startfile options; crt0 flavors. |
| |
| At the moment there are no gcrt0.o or mcrt0.o, but keep them here and |
| link them to crt0.o to be prepared. Use scrt0.c if running the |
| simulator, linear style, or s2crt0.c if fixed style. */ |
| /* We need to remove any previous definition (elfos.h). */ |
| #undef STARTFILE_SPEC |
| #define STARTFILE_SPEC \ |
| "%{sim2:s2crt0.o%s}\ |
| %{!sim2:%{sim:scrt0.o%s}\ |
| %{!sim:%{pg:gcrt0.o%s}\ |
| %{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}}\ |
| crtbegin.o%s" |
| |
| #undef ENDFILE_SPEC |
| #define ENDFILE_SPEC "crtend.o%s" |
| |
| #define EXTRA_SPECS \ |
| {"cpp_subtarget", CRIS_CPP_SUBTARGET_SPEC}, \ |
| {"cc1_subtarget", CRIS_CC1_SUBTARGET_SPEC}, \ |
| {"asm_subtarget", CRIS_ASM_SUBTARGET_SPEC}, \ |
| {"link_subtarget", CRIS_LINK_SUBTARGET_SPEC}, \ |
| CRIS_SUBTARGET_EXTRA_SPECS |
| |
| #define CRIS_SUBTARGET_EXTRA_SPECS |
| |
| |
| /* Node: Run-time Target */ |
| |
| #define TARGET_CPU_CPP_BUILTINS() \ |
| do \ |
| { \ |
| builtin_define_std ("cris"); \ |
| builtin_define_std ("CRIS"); \ |
| builtin_define_std ("GNU_CRIS"); \ |
| builtin_define ("__CRIS_ABI_version=2"); \ |
| builtin_assert ("cpu=cris"); \ |
| builtin_assert ("machine=cris"); \ |
| } \ |
| while (0) |
| |
| /* This needs to be at least 32 bits. */ |
| extern int target_flags; |
| |
| /* Currently this just affects alignment. FIXME: Redundant with |
| TARGET_ALIGN_BY_32, or put machine stuff here? */ |
| #define TARGET_MASK_SVINTO 1 |
| #define TARGET_SVINTO (target_flags & TARGET_MASK_SVINTO) |
| |
| /* If to use condition-codes generated by insns other than the |
| immediately preceding compare/test insn. |
| Used to check for errors in notice_update_cc. */ |
| #define TARGET_MASK_CCINIT 2 |
| #define TARGET_CCINIT (target_flags & TARGET_MASK_CCINIT) |
| |
| /* Debug option. */ |
| #define TARGET_MASK_PDEBUG 4 |
| #define TARGET_PDEBUG (target_flags & TARGET_MASK_PDEBUG) |
| |
| /* If to use side-effect patterns. Used to debug the [rx=ry+i] type |
| patterns. */ |
| #define TARGET_MASK_SIDE_EFFECT_PREFIXES 8 |
| #define TARGET_SIDE_EFFECT_PREFIXES \ |
| (target_flags & TARGET_MASK_SIDE_EFFECT_PREFIXES) |
| |
| /* If to expand mul into mstep. Only used when making libc.a. */ |
| #define TARGET_MASK_EXPAND_MUL 16 |
| #define TARGET_EXPAND_MUL (target_flags & TARGET_MASK_EXPAND_MUL) |
| |
| /* If to *keep* (not force) alignment of stack at 16 bits. */ |
| #define TARGET_MASK_STACK_ALIGN 32 |
| #define TARGET_STACK_ALIGN (target_flags & TARGET_MASK_STACK_ALIGN) |
| |
| /* If to do alignment on individual non-modifiable objects. */ |
| #define TARGET_MASK_CONST_ALIGN 64 |
| #define TARGET_CONST_ALIGN (target_flags & TARGET_MASK_CONST_ALIGN) |
| |
| /* If to do alignment on individual modifiable objects. */ |
| #define TARGET_MASK_DATA_ALIGN 128 |
| #define TARGET_DATA_ALIGN (target_flags & TARGET_MASK_DATA_ALIGN) |
| |
| /* If not to omit function prologue and epilogue. */ |
| #define TARGET_MASK_PROLOGUE_EPILOGUE 256 |
| #define TARGET_PROLOGUE_EPILOGUE (target_flags & TARGET_MASK_PROLOGUE_EPILOGUE) |
| |
| /* Instructions additions from Etrax 4 and up. |
| (Just "lz", which we don't really generate from GCC -- yet). */ |
| #define TARGET_MASK_ETRAX4_ADD 512 |
| #define TARGET_ETRAX4_ADD (target_flags & TARGET_MASK_ETRAX4_ADD) |
| |
| /* Say that all alignment specifications say to prefer 32 rather |
| than 16 bits. */ |
| #define TARGET_MASK_ALIGN_BY_32 1024 |
| #define TARGET_ALIGN_BY_32 (target_flags & TARGET_MASK_ALIGN_BY_32) |
| |
| /* This condition is of limited use, as gcc is riddled with #ifdef:s |
| controlling this, rather than if (...):s. */ |
| #define TARGET_MASK_ELF 2048 |
| #define TARGET_ELF (target_flags & TARGET_MASK_ELF) |
| |
| /* Currently just used to error-check other options. Note that this is |
| *not* set for -melinux. */ |
| #define TARGET_MASK_LINUX 4096 |
| #define TARGET_LINUX (target_flags & TARGET_MASK_LINUX) |
| |
| /* There's a small setup cost with using GOTPLT references, but should |
| in total be a win both in code-size and execution-time. */ |
| #define TARGET_MASK_AVOID_GOTPLT 8192 |
| #define TARGET_AVOID_GOTPLT (target_flags & TARGET_MASK_AVOID_GOTPLT) |
| |
| /* Whether or not to work around multiplication instruction hardware bug |
| when generating code for models where it may be present. From the |
| trouble report for Etrax 100 LX: "A multiply operation may cause |
| incorrect cache behaviour under some specific circumstances. The |
| problem can occur if the instruction following the multiply instruction |
| causes a cache miss, and multiply operand 1 (source operand) bits |
| [31:27] matches the logical mapping of the mode register address |
| (0xb0....), and bits [9:2] of operand 1 matches the TLB register |
| address (0x258-0x25f). There is such a mapping in kernel mode or when |
| the MMU is off. Normally there is no such mapping in user mode, and |
| the problem will therefore probably not occur in Linux user mode |
| programs." |
| |
| We have no sure-fire way to know from within GCC that we're compiling a |
| user program. For example, -fpic/PIC is used in libgcc which is linked |
| into the kernel. However, the workaround option -mno-mul-bug can be |
| safely used per-package when compiling programs. The same goes for |
| general user-only libraries such as glibc, since there's no user-space |
| driver-like program that gets a mapping of I/O registers (all on the |
| same page, including the TLB registers). */ |
| #define TARGET_MASK_MUL_BUG 16384 |
| #define TARGET_MUL_BUG (target_flags & TARGET_MASK_MUL_BUG) |
| |
| #define TARGET_SWITCHES \ |
| { \ |
| {"mul-bug-workaround", TARGET_MASK_MUL_BUG, \ |
| N_("Work around bug in multiplication instruction")}, \ |
| {"no-mul-bug-workaround", -TARGET_MASK_MUL_BUG, ""}, \ |
| /* No "no-etrax" as it does not really imply any model. \ |
| On the other hand, "etrax" implies the common (and large) \ |
| subset matching all models. */ \ |
| {"etrax4", TARGET_MASK_ETRAX4_ADD, \ |
| N_("Compile for ETRAX 4 (CRIS v3)")}, \ |
| {"no-etrax4", -TARGET_MASK_ETRAX4_ADD, ""}, \ |
| {"etrax100", (TARGET_MASK_SVINTO \ |
| + TARGET_MASK_ETRAX4_ADD \ |
| + TARGET_MASK_ALIGN_BY_32), \ |
| N_("Compile for ETRAX 100 (CRIS v8)")}, \ |
| {"no-etrax100", -(TARGET_MASK_SVINTO \ |
| + TARGET_MASK_ETRAX4_ADD), ""}, \ |
| {"pdebug", TARGET_MASK_PDEBUG, \ |
| N_("Emit verbose debug information in assembly code")}, \ |
| {"no-pdebug", -TARGET_MASK_PDEBUG, ""}, \ |
| {"cc-init", TARGET_MASK_CCINIT, \ |
| N_("Do not use condition codes from normal instructions")}, \ |
| {"no-cc-init", -TARGET_MASK_CCINIT, ""}, \ |
| {"side-effects", TARGET_MASK_SIDE_EFFECT_PREFIXES, ""}, \ |
| {"no-side-effects", -TARGET_MASK_SIDE_EFFECT_PREFIXES, \ |
| N_("Do not emit addressing modes with side-effect assignment")}, \ |
| {"stack-align", TARGET_MASK_STACK_ALIGN, ""}, \ |
| {"no-stack-align", -TARGET_MASK_STACK_ALIGN, \ |
| N_("Do not tune stack alignment")}, \ |
| {"data-align", TARGET_MASK_DATA_ALIGN, ""}, \ |
| {"no-data-align", -TARGET_MASK_DATA_ALIGN, \ |
| N_("Do not tune writable data alignment")}, \ |
| {"const-align", TARGET_MASK_CONST_ALIGN, ""}, \ |
| {"no-const-align", -TARGET_MASK_CONST_ALIGN, \ |
| N_("Do not tune code and read-only data alignment")}, \ |
| {"32-bit", (TARGET_MASK_STACK_ALIGN \ |
| + TARGET_MASK_CONST_ALIGN \ |
| + TARGET_MASK_DATA_ALIGN \ |
| + TARGET_MASK_ALIGN_BY_32), ""}, \ |
| {"32bit", (TARGET_MASK_STACK_ALIGN \ |
| + TARGET_MASK_CONST_ALIGN \ |
| + TARGET_MASK_DATA_ALIGN \ |
| + TARGET_MASK_ALIGN_BY_32), \ |
| N_("Align code and data to 32 bits")}, \ |
| {"16-bit", (TARGET_MASK_STACK_ALIGN \ |
| + TARGET_MASK_CONST_ALIGN \ |
| + TARGET_MASK_DATA_ALIGN), ""}, \ |
| {"16bit", (TARGET_MASK_STACK_ALIGN \ |
| + TARGET_MASK_CONST_ALIGN \ |
| + TARGET_MASK_DATA_ALIGN), ""}, \ |
| {"8-bit", -(TARGET_MASK_STACK_ALIGN \ |
| + TARGET_MASK_CONST_ALIGN \ |
| + TARGET_MASK_DATA_ALIGN), ""}, \ |
| {"8bit", -(TARGET_MASK_STACK_ALIGN \ |
| + TARGET_MASK_CONST_ALIGN \ |
| + TARGET_MASK_DATA_ALIGN), \ |
| N_("Don't align items in code or data")}, \ |
| {"prologue-epilogue", TARGET_MASK_PROLOGUE_EPILOGUE, ""}, \ |
| {"no-prologue-epilogue", -TARGET_MASK_PROLOGUE_EPILOGUE, \ |
| N_("Do not emit function prologue or epilogue")}, \ |
| /* We have to handle this m-option here since we can't wash it off in \ |
| both CC1_SPEC and CC1PLUS_SPEC. */ \ |
| {"best-lib-options", 0, \ |
| N_("Use the most feature-enabling options allowed by other options")}, \ |
| \ |
| /* We must call it "override-" since calling it "no-" will cause \ |
| gcc.c to forget it, if there's a "later" -mbest-lib-options. \ |
| Kludgy, but needed for some multilibbed files. */ \ |
| {"override-best-lib-options", 0, \ |
| N_("Override -mbest-lib-options")}, \ |
| CRIS_SUBTARGET_SWITCHES \ |
| {"", TARGET_DEFAULT | CRIS_SUBTARGET_DEFAULT, ""}} \ |
| |
| /* For the cris-*-elf subtarget. */ |
| #define CRIS_SUBTARGET_SWITCHES \ |
| {"elf", 0, ""}, |
| |
| /* Default target_flags if no switches specified. */ |
| #ifndef TARGET_DEFAULT |
| # define TARGET_DEFAULT \ |
| (TARGET_MASK_SIDE_EFFECT_PREFIXES + TARGET_MASK_STACK_ALIGN \ |
| + TARGET_MASK_CONST_ALIGN + TARGET_MASK_DATA_ALIGN \ |
| + TARGET_MASK_PROLOGUE_EPILOGUE + TARGET_MASK_MUL_BUG) |
| #endif |
| |
| /* For the cris-*-elf subtarget. */ |
| #define CRIS_SUBTARGET_DEFAULT TARGET_MASK_ELF |
| |
| #define CRIS_CPU_BASE 0 |
| #define CRIS_CPU_ETRAX4 3 /* Just lz added. */ |
| #define CRIS_CPU_SVINTO 8 /* Added swap, jsrc & Co., 32-bit accesses. */ |
| #define CRIS_CPU_NG 10 /* Added mul[su]. */ |
| |
| /* Local, providing a default for cris_cpu_version. */ |
| #define CRIS_DEFAULT_CPU_VERSION CRIS_CPU_BASE |
| |
| #define TARGET_HAS_MUL_INSNS (cris_cpu_version >= CRIS_CPU_NG) |
| |
| #define TARGET_OPTIONS \ |
| {{"cpu=", &cris_cpu_str, "", 0}, \ |
| {"arch=", &cris_cpu_str, \ |
| N_("Generate code for the specified chip or CPU version"), 0}, \ |
| {"tune=", &cris_tune_str, \ |
| N_("Tune alignment for the specified chip or CPU version"), 0}, \ |
| {"max-stackframe=", &cris_max_stackframe_str, \ |
| N_("Warn when a stackframe is larger than the specified size"), 0}, \ |
| CRIS_SUBTARGET_LONG_OPTIONS \ |
| {"ax-stackframe=", &cris_max_stackframe_str, "", 0} } |
| |
| #define CRIS_SUBTARGET_LONG_OPTIONS |
| |
| /* Print subsidiary information on the compiler version in use. |
| Do not use VD.D syntax (D=digit), since this will cause confusion |
| with the base gcc version among users, when we ask which version of |
| gcc-cris they are using. Please use some flavor of "R<number>" for |
| the version (no need for major.minor versions, I believe). */ |
| #define TARGET_VERSION \ |
| fprintf (stderr, " [Axis CRIS%s]", CRIS_SUBTARGET_VERSION) |
| |
| /* For the cris-*-elf subtarget. */ |
| #define CRIS_SUBTARGET_VERSION " - generic ELF" |
| |
| #define OVERRIDE_OPTIONS cris_override_options () |
| |
| /* The following gives optimal code for gcc-2.7.2, but *may* be subject |
| to change. Omitting flag_force_addr gives .1-.7% faster code for gcc |
| *only*, but 1.3% larger code. On ipps it gives 5.3-10.6% slower |
| code(!) and 0.3% larger code. For products, images gets .1-1.8% |
| larger. Do not set strict aliasing from optimization options. */ |
| #define OPTIMIZATION_OPTIONS(OPTIMIZE, SIZE) \ |
| do \ |
| { \ |
| if ((OPTIMIZE) >= 2 || (SIZE)) \ |
| { \ |
| flag_force_addr = 1; \ |
| flag_omit_frame_pointer = 1; \ |
| } \ |
| } \ |
| while (0) |
| |
| |
| /* Node: Storage Layout */ |
| |
| #define BITS_BIG_ENDIAN 0 |
| |
| #define BYTES_BIG_ENDIAN 0 |
| |
| /* WORDS_BIG_ENDIAN is not defined in the hardware, but for consistency, |
| we use little-endianness, and we may also be able to use |
| post-increment on DImode indirect. */ |
| #define WORDS_BIG_ENDIAN 0 |
| |
| #define UNITS_PER_WORD 4 |
| |
| /* A combination of defining PROMOTE_MODE, PROMOTE_FUNCTION_ARGS, |
| PROMOTE_FOR_CALL_ONLY and *not* defining PROMOTE_PROTOTYPES gives the |
| best code size and speed for gcc, ipps and products in gcc-2.7.2. */ |
| #define CRIS_PROMOTED_MODE(MODE, UNSIGNEDP, TYPE) \ |
| (GET_MODE_CLASS (MODE) == MODE_INT && GET_MODE_SIZE (MODE) < 4) \ |
| ? SImode : MODE |
| |
| #define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE) \ |
| (MODE) = CRIS_PROMOTED_MODE (MODE, UNSIGNEDP, TYPE) |
| |
| #define PROMOTE_FUNCTION_ARGS |
| |
| /* Defining PROMOTE_FUNCTION_RETURN in gcc-2.7.2 uncovers bug 981110 (even |
| if defining FUNCTION_VALUE with MODE as PROMOTED_MODE ;-) |
| |
| FIXME: Report this when cris.h is part of GCC, so others can easily |
| see the problem. Maybe check other systems that define |
| PROMOTE_FUNCTION_RETURN. */ |
| #define PROMOTE_FOR_CALL_ONLY |
| |
| /* We will be using prototype promotion, so they will be 32 bit. */ |
| #define PARM_BOUNDARY 32 |
| |
| /* Stack boundary is guided by -mstack-align, -mno-stack-align, |
| -malign. |
| Old comment: (2.1: still valid in 2.7.2?) |
| Note that to make this macro affect the alignment of stack |
| locals, a fix was required, and special precautions when handling |
| the stack pointer in various other macros (TARGET_ASM_FUNCTION_PROLOGUE |
| et al) were required. See file "function.c". If you would just define |
| this macro, it would only affect the builtin alloca and variable |
| local data (non-ANSI, non-K&R, Gnu C extension). */ |
| #define STACK_BOUNDARY \ |
| (TARGET_STACK_ALIGN ? (TARGET_ALIGN_BY_32 ? 32 : 16) : 8) |
| |
| #define FUNCTION_BOUNDARY 16 |
| |
| /* Do not change BIGGEST_ALIGNMENT (when optimizing), as it will affect |
| strange places, at least in 2.1. */ |
| #define BIGGEST_ALIGNMENT 8 |
| |
| /* If -m16bit, -m16-bit, -malign or -mdata-align, |
| align everything to 16 bit. */ |
| #define DATA_ALIGNMENT(TYPE, BASIC_ALIGN) \ |
| (TARGET_DATA_ALIGN \ |
| ? (TARGET_ALIGN_BY_32 \ |
| ? (BASIC_ALIGN < 32 ? 32 : BASIC_ALIGN) \ |
| : (BASIC_ALIGN < 16 ? 16 : BASIC_ALIGN)) : BASIC_ALIGN) |
| |
| /* Note that CONSTANT_ALIGNMENT has the effect of making gcc believe that |
| ALL references to constant stuff (in code segment, like strings) has |
| this alignment. That is a rather rushed assumption. Luckily we do not |
| care about the "alignment" operand to builtin memcpy (only place where |
| it counts), so it doesn't affect any bad spots. */ |
| #define CONSTANT_ALIGNMENT(CONSTANT, BASIC_ALIGN) \ |
| (TARGET_CONST_ALIGN \ |
| ? (TARGET_ALIGN_BY_32 \ |
| ? (BASIC_ALIGN < 32 ? 32 : BASIC_ALIGN) \ |
| : (BASIC_ALIGN < 16 ? 16 : BASIC_ALIGN)) : BASIC_ALIGN) |
| |
| /* FIXME: Define LOCAL_ALIGNMENT for word and dword or arrays and |
| structures (if -mstack-align=), and check that it is good. */ |
| |
| #define EMPTY_FIELD_BOUNDARY 8 |
| |
| #define STRUCTURE_SIZE_BOUNDARY 8 |
| |
| #define STRICT_ALIGNMENT 0 |
| |
| /* Remove any previous definition (elfos.h). |
| ??? If it wasn't for all the other stuff that affects layout of |
| structures and bit-fields, this could presumably cause incompatibility |
| with other GNU/Linux ports (i.e. elfos.h users). */ |
| #undef PCC_BITFIELD_TYPE_MATTERS |
| |
| /* This is only used for non-scalars. Strange stuff happens to structs |
| (FIXME: What?) if we use anything larger than largest actually used |
| datum size, so lets make it 32. The type "long long" will still work |
| as usual. We can still have DImode insns, but they will only be used |
| for scalar data (i.e. long long). */ |
| #define MAX_FIXED_MODE_SIZE 32 |
| |
| |
| /* Node: Type Layout */ |
| |
| /* Note that DOUBLE_TYPE_SIZE is not defined anymore, since the default |
| value gives a 64-bit double, which is what we now use. */ |
| |
| /* For compatibility and historical reasons, a char should be signed. */ |
| #define DEFAULT_SIGNED_CHAR 1 |
| |
| /* No DEFAULT_SHORT_ENUMS, please. */ |
| |
| /* Note that WCHAR_TYPE_SIZE is used in cexp.y, |
| where TARGET_SHORT is not available. */ |
| #undef WCHAR_TYPE |
| #define WCHAR_TYPE "long int" |
| |
| #undef WCHAR_TYPE_SIZE |
| #define WCHAR_TYPE_SIZE 32 |
| |
| |
| /* Node: Register Basics */ |
| |
| /* We count all 16 non-special registers, SRP and a faked argument |
| pointer register. */ |
| #define FIRST_PSEUDO_REGISTER (16 + 1 + 1) |
| |
| /* For CRIS, these are r15 (pc) and r14 (sp). Register r8 is used as a |
| frame-pointer, but is not fixed. SRP is not included in general |
| registers and will not be used automatically. All other special |
| registers are fixed at the moment. The faked argument pointer register |
| is fixed too. */ |
| #define FIXED_REGISTERS \ |
| {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1} |
| |
| /* Register r9 is used for structure-address, r10-r13 for parameters, |
| r10- for return values. */ |
| #define CALL_USED_REGISTERS \ |
| {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1} |
| |
| #define CONDITIONAL_REGISTER_USAGE cris_conditional_register_usage () |
| |
| |
| /* Node: Allocation Order */ |
| |
| /* We need this on CRIS, because call-used regs should be used first, |
| (so we don't need to push). Else start using registers from r0 and up. |
| This preference is mainly because if we put call-used-regs from r0 |
| and up, then we can't use movem to push the rest, (which have to be |
| saved if we use them, and movem has to start with r0). |
| Change here if you change which registers to use as call registers. |
| |
| The actual need to explicitly prefer call-used registers improved the |
| situation a lot for 2.1, but might not actually be needed anymore. |
| Still, this order reflects what GCC should find out by itself, so it |
| probably does not hurt. |
| |
| Order of preference: Call-used-regs first, then r0 and up, last fp & |
| sp & pc as fillers. |
| Call-used regs in opposite order, so they will cause less conflict if |
| a function has few args (<= 3) and it wants a scratch reg. |
| Use struct-return address first, since very few functions use |
| structure return values so it is likely to be available. */ |
| #define REG_ALLOC_ORDER \ |
| {9, 13, 12, 11, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 14, 15, 16, 17} |
| |
| |
| /* Node: Values in Registers */ |
| |
| /* The VOIDmode test is so we can omit mode on anonymous insns. FIXME: |
| Still needed in 2.9x, at least for Axis-20000319. */ |
| #define HARD_REGNO_NREGS(REGNO, MODE) \ |
| (MODE == VOIDmode \ |
| ? 1 : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) |
| |
| /* CRIS permits all registers to hold all modes. */ |
| #define HARD_REGNO_MODE_OK(REGNO, MODE) 1 |
| |
| #define MODES_TIEABLE_P(MODE1, MODE2) 1 |
| |
| |
| /* Node: Leaf Functions */ |
| /* (no definitions) */ |
| |
| /* Node: Stack Registers */ |
| /* (no definitions) */ |
| |
| |
| /* Node: Register Classes */ |
| |
| /* CRIS has only one kind of registers, so NO_REGS and ALL_REGS |
| are the only classes. FIXME: It actually makes sense to have another |
| class for special registers, and yet another class for the |
| multiply-overflow register in v10; then a class for the return |
| register also makes sense. */ |
| enum reg_class {NO_REGS, ALL_REGS, LIM_REG_CLASSES}; |
| |
| #define N_REG_CLASSES (int) LIM_REG_CLASSES |
| |
| #define REG_CLASS_NAMES {"NO_REGS", "ALL_REGS"} |
| |
| #define GENERAL_REGS ALL_REGS |
| |
| /* Count in the faked argument register in GENERAL_REGS. Keep out SRP. */ |
| #define REG_CLASS_CONTENTS {{0}, {0x2ffff}} |
| |
| #define REGNO_REG_CLASS(REGNO) GENERAL_REGS |
| |
| #define BASE_REG_CLASS GENERAL_REGS |
| |
| #define INDEX_REG_CLASS GENERAL_REGS |
| |
| /* Get reg_class from a letter such as appears in the machine |
| description. No letters are used, since 'r' is used for any |
| register. */ |
| #define REG_CLASS_FROM_LETTER(C) NO_REGS |
| |
| /* Since it uses reg_renumber, it is safe only once reg_renumber |
| has been allocated, which happens in local-alloc.c. */ |
| #define REGNO_OK_FOR_BASE_P(REGNO) \ |
| ((REGNO) <= CRIS_LAST_GENERAL_REGISTER \ |
| || (REGNO) == ARG_POINTER_REGNUM \ |
| || (unsigned) reg_renumber[REGNO] <= CRIS_LAST_GENERAL_REGISTER \ |
| || (unsigned) reg_renumber[REGNO] == ARG_POINTER_REGNUM) |
| |
| /* See REGNO_OK_FOR_BASE_P. */ |
| #define REGNO_OK_FOR_INDEX_P(REGNO) REGNO_OK_FOR_BASE_P(REGNO) |
| |
| /* It seems like gcc (2.7.2 and 2.9x of 2000-03-22) may send "NO_REGS" as |
| the class for a constant (testcase: __Mul in arit.c). To avoid forcing |
| out a constant into the constant pool, we will trap this case and |
| return something a bit more sane. FIXME: Check if this is a bug. */ |
| #define PREFERRED_RELOAD_CLASS(X, CLASS) \ |
| ((CLASS) == NO_REGS ? GENERAL_REGS : (CLASS)) |
| |
| /* For CRIS, this is always the size of MODE in words, |
| since all registers are the same size. To use omitted modes in |
| patterns with reload constraints, you must say the widest size |
| which is allowed for VOIDmode. |
| FIXME: Does that still apply for gcc-2.9x? Keep poisoned until such |
| patterns are added back. News: 2001-03-16: Happens as early as the |
| underscore-test. */ |
| #define CLASS_MAX_NREGS(CLASS, MODE) \ |
| ((MODE) == VOIDmode \ |
| ? 1 /* + cris_fatal ("CLASS_MAX_NREGS with VOIDmode") */ \ |
| : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) |
| |
| /* We are now out of letters; we could use ten more. This forces us to |
| use C-code in the 'md' file. FIXME: Use some EXTRA_CONSTRAINTS. */ |
| #define CONST_OK_FOR_LETTER_P(VALUE, C) \ |
| ( \ |
| /* MOVEQ, CMPQ, ANDQ, ORQ. */ \ |
| (C) == 'I' ? (VALUE) >= -32 && (VALUE) <= 31 : \ |
| /* ADDQ, SUBQ. */ \ |
| (C) == 'J' ? (VALUE) >= 0 && (VALUE) <= 63 : \ |
| /* ASRQ, BTSTQ, LSRQ, LSLQ. */ \ |
| (C) == 'K' ? (VALUE) >= 0 && (VALUE) <= 31 : \ |
| /* A 16-bit signed number. */ \ |
| (C) == 'L' ? (VALUE) >= -32768 && (VALUE) <= 32767 : \ |
| /* The constant 0 for CLEAR. */ \ |
| (C) == 'M' ? (VALUE) == 0 : \ |
| /* A negative ADDQ or SUBQ. */ \ |
| (C) == 'N' ? (VALUE) >= -63 && (VALUE) < 0 : \ |
| /* Quickened ints, QI and HI. */ \ |
| (C) == 'O' ? (VALUE) >= 0 && (VALUE) <= 65535 \ |
| && ((VALUE) >= (65535-31) \ |
| || ((VALUE) >= (255-31) \ |
| && (VALUE) <= 255 )) : \ |
| /* A 16-bit number signed *or* unsigned. */ \ |
| (C) == 'P' ? (VALUE) >= -32768 && (VALUE) <= 65535 : \ |
| 0) |
| |
| /* It is really simple to make up a 0.0; it is the same as int-0 in |
| IEEE754. */ |
| #define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ |
| ((C) == 'G' && ((VALUE) == CONST0_RTX (DFmode) \ |
| || (VALUE) == CONST0_RTX (SFmode))) |
| |
| /* We need this on cris to distinguish delay-slottable addressing modes. */ |
| #define EXTRA_CONSTRAINT(X, C) \ |
| ( \ |
| /* Slottable address mode? */ \ |
| (C) == 'Q' ? EXTRA_CONSTRAINT_Q (X) : \ |
| /* Operand to BDAP or BIAP? */ \ |
| (C) == 'R' ? EXTRA_CONSTRAINT_R (X) : \ |
| /* A local PIC symbol? */ \ |
| (C) == 'S' ? EXTRA_CONSTRAINT_S (X) : \ |
| /* A three-address addressing-mode? */ \ |
| (C) == 'T' ? EXTRA_CONSTRAINT_T (X) : \ |
| /* A global PIC symbol? */ \ |
| (C) == 'U' ? EXTRA_CONSTRAINT_U (X) : \ |
| 0) |
| |
| #define EXTRA_CONSTRAINT_Q(X) \ |
| ( \ |
| /* Slottable addressing modes: \ |
| A register? FIXME: Unnecessary. */ \ |
| (BASE_P (X) && REGNO (X) != CRIS_PC_REGNUM) \ |
| /* Indirect register: [reg]? */ \ |
| || (GET_CODE (X) == MEM && BASE_P (XEXP (X, 0)) \ |
| && REGNO (XEXP (X, 0)) != CRIS_PC_REGNUM) \ |
| ) |
| |
| #define EXTRA_CONSTRAINT_R(X) \ |
| ( \ |
| /* An operand to BDAP or BIAP: \ |
| A BIAP; r.S? */ \ |
| BIAP_INDEX_P (X) \ |
| /* A [reg] or (int) [reg], maybe with post-increment. */ \ |
| || BDAP_INDEX_P (X) \ |
| || CONSTANT_INDEX_P (X) \ |
| ) |
| |
| #define EXTRA_CONSTRAINT_T(X) \ |
| ( \ |
| /* Memory three-address operand. All are indirect-memory: */ \ |
| GET_CODE (X) == MEM \ |
| && ((GET_CODE (XEXP (X, 0)) == MEM \ |
| /* Double indirect: [[reg]] or [[reg+]]? */ \ |
| && (BASE_OR_AUTOINCR_P (XEXP (XEXP (X, 0), 0)))) \ |
| /* Just an explicit indirect reference: [const]? */ \ |
| || CONSTANT_P (XEXP (X, 0)) \ |
| /* Something that is indexed; [...+...]? */ \ |
| || (GET_CODE (XEXP (X, 0)) == PLUS \ |
| /* A BDAP constant: [reg+(8|16|32)bit offset]? */ \ |
| && ((BASE_P (XEXP (XEXP (X, 0), 0)) \ |
| && CONSTANT_INDEX_P (XEXP (XEXP (X, 0), 1))) \ |
| /* Swap arguments to the above. FIXME: gcc-2.9x? */ \ |
| || (BASE_P (XEXP (XEXP (X, 0), 1)) \ |
| && CONSTANT_INDEX_P (XEXP (XEXP (X, 0), 0))) \ |
| /* A BDAP register: [reg+[reg(+)].S]? */ \ |
| || (BASE_P (XEXP (XEXP (X, 0), 0)) \ |
| && BDAP_INDEX_P(XEXP(XEXP(X, 0), 1))) \ |
| /* Same, but with swapped arguments. */ \ |
| || (BASE_P (XEXP (XEXP (X, 0), 1)) \ |
| && BDAP_INDEX_P (XEXP (XEXP (X, 0), 0))) \ |
| /* A BIAP: [reg+reg.S]. */ \ |
| || (BASE_P (XEXP (XEXP (X, 0), 0)) \ |
| && BIAP_INDEX_P (XEXP (XEXP (X, 0), 1))) \ |
| /* Same, but with swapped arguments. */ \ |
| || (BASE_P (XEXP (XEXP (X, 0), 1)) \ |
| && BIAP_INDEX_P (XEXP (XEXP (X, 0), 0)))))) \ |
| ) |
| |
| #define EXTRA_CONSTRAINT_S(X) \ |
| (flag_pic && CONSTANT_P (X) && cris_gotless_symbol (X)) |
| |
| #define EXTRA_CONSTRAINT_U(X) \ |
| (flag_pic && CONSTANT_P (X) && cris_got_symbol (X)) |
| |
| |
| /* Node: Frame Layout */ |
| |
| #define STACK_GROWS_DOWNWARD |
| #define FRAME_GROWS_DOWNWARD |
| |
| /* It seems to be indicated in the code (at least 2.1) that this is |
| better a constant, and best 0. */ |
| #define STARTING_FRAME_OFFSET 0 |
| |
| #define FIRST_PARM_OFFSET(FNDECL) 0 |
| |
| #define RETURN_ADDR_RTX(COUNT, FRAMEADDR) \ |
| cris_return_addr_rtx (COUNT, FRAMEADDR) |
| |
| #define INCOMING_RETURN_ADDR_RTX gen_rtx (REG, Pmode, CRIS_SRP_REGNUM) |
| |
| /* FIXME: Any __builtin_eh_return callers must not return anything and |
| there must not be collisions with incoming parameters. Luckily the |
| number of __builtin_eh_return callers is limited. For now return |
| parameter registers in reverse order and hope for the best. */ |
| #define EH_RETURN_DATA_REGNO(N) \ |
| (IN_RANGE ((N), 0, 3) ? (CRIS_FIRST_ARG_REG + 3 - (N)) : INVALID_REGNUM) |
| |
| /* Store the stack adjustment in the structure-return-address register. */ |
| #define CRIS_STACKADJ_REG STRUCT_VALUE_REGNUM |
| #define EH_RETURN_STACKADJ_RTX gen_rtx_REG (SImode, CRIS_STACKADJ_REG) |
| |
| #define EH_RETURN_HANDLER_RTX \ |
| cris_return_addr_rtx (0, NULL) |
| |
| #define INIT_EXPANDERS cris_init_expanders () |
| |
| /* FIXME: Move this to right node (it's not documented properly yet). */ |
| #define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (CRIS_SRP_REGNUM) |
| |
| /* FIXME: Move this to right node (it's not documented properly yet). |
| FIXME: Check what alignment we can assume regarding |
| TARGET_STACK_ALIGN and TARGET_ALIGN_BY_32. */ |
| #define DWARF_CIE_DATA_ALIGNMENT -1 |
| |
| /* If we would ever need an exact mapping between canonical register |
| number and dwarf frame register, we would either need to include all |
| registers in the gcc description (with some marked fixed of course), or |
| an inverse mapping from dwarf register to gcc register. There is one |
| need in dwarf2out.c:expand_builtin_init_dwarf_reg_sizes. Right now, I |
| don't see that we need exact correspondence between DWARF *frame* |
| registers and DBX_REGISTER_NUMBER, so map them onto GCC registers. */ |
| #define DWARF_FRAME_REGNUM(REG) (REG) |
| |
| /* Node: Stack Checking */ |
| /* (no definitions) FIXME: Check. */ |
| |
| /* Node: Frame Registers */ |
| |
| #define STACK_POINTER_REGNUM 14 |
| |
| /* Register used for frame pointer. This is also the last of the saved |
| registers, when a frame pointer is not used. */ |
| #define FRAME_POINTER_REGNUM 8 |
| |
| /* Faked register, is always eliminated. We need it to eliminate |
| allocating stack slots for the return address and the frame pointer. */ |
| #define ARG_POINTER_REGNUM 17 |
| |
| #define STATIC_CHAIN_REGNUM 7 |
| |
| |
| /* Node: Elimination */ |
| |
| /* Really only needed if the stack frame has variable length (alloca |
| or variable sized local arguments (GNU C extension). */ |
| #define FRAME_POINTER_REQUIRED 0 |
| |
| #define ELIMINABLE_REGS \ |
| {{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ |
| {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ |
| {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}} |
| |
| /* We need not worry about when the frame-pointer is required for other |
| reasons. */ |
| #define CAN_ELIMINATE(FROM, TO) 1 |
| |
| #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ |
| (OFFSET) = cris_initial_elimination_offset (FROM, TO) |
| |
| |
| /* Node: Stack Arguments */ |
| |
| /* Since many parameters take up one register each in any case, |
| PROMOTE_PROTOTYPES would seem like a good idea, but measurements |
| indicate that a combination using PROMOTE_MODE is better. */ |
| |
| #define ACCUMULATE_OUTGOING_ARGS 1 |
| |
| #define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACKSIZE) 0 |
| |
| |
| /* Node: Register Arguments */ |
| |
| /* The void_type_node is sent as a "closing" call. We have to stop it |
| since it's invalid to FUNCTION_ARG_PASS_BY_REFERENCE (or was invalid at |
| some time). */ |
| #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ |
| ((CUM).regs < CRIS_MAX_ARGS_IN_REGS \ |
| && (TYPE) != void_type_node \ |
| && ! FUNCTION_ARG_PASS_BY_REFERENCE (CUM, MODE, TYPE, NAMED) \ |
| ? gen_rtx (REG, MODE, (CRIS_FIRST_ARG_REG) + (CUM).regs) \ |
| : NULL_RTX) |
| |
| /* The differences between this and the previous, is that this one checks |
| that an argument is named, since incoming stdarg/varargs arguments are |
| pushed onto the stack, and we don't have to check against the "closing" |
| void_type_node TYPE parameter. */ |
| #define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \ |
| (((NAMED) && (CUM).regs < CRIS_MAX_ARGS_IN_REGS \ |
| && ! FUNCTION_ARG_PASS_BY_REFERENCE (CUM, MODE, TYPE, NAMED)) \ |
| ? gen_rtx (REG, MODE, CRIS_FIRST_ARG_REG + (CUM).regs) \ |
| : NULL_RTX) |
| |
| #define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \ |
| (((CUM).regs == (CRIS_MAX_ARGS_IN_REGS - 1) \ |
| && !MUST_PASS_IN_STACK (MODE, TYPE) \ |
| && CRIS_FUNCTION_ARG_SIZE (MODE, TYPE) > 4 \ |
| && CRIS_FUNCTION_ARG_SIZE (MODE, TYPE) <= 8) \ |
| ? 1 : 0) |
| |
| /* Structs may be passed by value, but they must not be more than 8 |
| bytes long. If you tweak this, don't forget to adjust |
| cris_expand_builtin_va_arg. */ |
| #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ |
| (MUST_PASS_IN_STACK (MODE, TYPE) \ |
| || CRIS_FUNCTION_ARG_SIZE (MODE, TYPE) > 8) \ |
| |
| /* Contrary to what you'd believe, defining FUNCTION_ARG_CALLEE_COPIES |
| seems like a (small total) loss, at least for gcc-2.7.2 compiling and |
| running gcc-2.1 (small win in size, small loss running -- 100.1%), |
| and similarly for size for products (.1 .. .3% bloat, sometimes win). |
| Due to the empirical likeliness of making slower code, it is not |
| defined. */ |
| |
| /* This no longer *needs* to be a structure; but keeping it as such should |
| not hurt (and hacking the ABI is simpler). */ |
| #define CUMULATIVE_ARGS struct cum_args |
| struct cum_args {int regs;}; |
| |
| /* The regs member is an integer, the number of arguments got into |
| registers so far. */ |
| #define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \ |
| ((CUM).regs = 0) |
| |
| #define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ |
| ((CUM).regs \ |
| = (FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ |
| ? (CRIS_MAX_ARGS_IN_REGS) + 1 \ |
| : ((CUM).regs \ |
| + (3 + (CRIS_FUNCTION_ARG_SIZE (MODE, TYPE))) / 4))) |
| |
| #define FUNCTION_ARG_REGNO_P(REGNO) \ |
| ((REGNO) >= CRIS_FIRST_ARG_REG \ |
| && (REGNO) < CRIS_FIRST_ARG_REG + (CRIS_MAX_ARGS_IN_REGS)) |
| |
| |
| /* Node: Scalar Return */ |
| |
| /* Let's assume all functions return in r[CRIS_FIRST_ARG_REG] for the |
| time being. */ |
| #define FUNCTION_VALUE(VALTYPE, FUNC) \ |
| gen_rtx (REG, TYPE_MODE (VALTYPE), CRIS_FIRST_ARG_REG) |
| |
| #define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, CRIS_FIRST_ARG_REG) |
| |
| #define FUNCTION_VALUE_REGNO_P(N) ((N) == CRIS_FIRST_ARG_REG) |
| |
| |
| /* Node: Aggregate Return */ |
| |
| #if 0 |
| /* FIXME: Let's try this some time, so we return structures in registers. |
| We would cast the result of int_size_in_bytes to unsigned, so we will |
| get a huge number for "structures" of variable size (-1). */ |
| #define RETURN_IN_MEMORY(TYPE) \ |
| ((unsigned) int_size_in_bytes (TYPE) > CRIS_MAX_ARGS_IN_REGS * UNITS_PER_WORD) |
| #endif |
| |
| #define STRUCT_VALUE_REGNUM ((CRIS_FIRST_ARG_REG) - 1) |
| |
| |
| /* Node: Caller Saves */ |
| /* (no definitions) */ |
| |
| /* Node: Function entry */ |
| |
| /* See cris.c for TARGET_ASM_FUNCTION_PROLOGUE and |
| TARGET_ASM_FUNCTION_EPILOGUE. */ |
| |
| /* If the epilogue uses the "ret" insn, we need to fill the |
| delay slot. */ |
| #define DELAY_SLOTS_FOR_EPILOGUE cris_delay_slots_for_epilogue () |
| |
| #define ELIGIBLE_FOR_EPILOGUE_DELAY(INSN, N) \ |
| cris_eligible_for_epilogue_delay (INSN) |
| |
| /* Node: Profiling */ |
| |
| #define FUNCTION_PROFILER(FILE, LABELNO) \ |
| error ("no FUNCTION_PROFILER for CRIS") |
| |
| /* FIXME: Some of the undefined macros might be mandatory. If so, fix |
| documentation. */ |
| |
| |
| /* Node: Varargs */ |
| |
| /* We save the register number of the first anonymous argument in |
| first_vararg_reg, and take care of this in the function prologue. |
| This behavior is used by at least one more port (the ARM?), but |
| may be unsafe when compiling nested functions. (With varargs? Hairy.) |
| Note that nested-functions is a GNU C extension. |
| |
| FIXME: We can actually put the size in PRETEND and deduce the number |
| of registers from it in the prologue and epilogue. */ |
| #define SETUP_INCOMING_VARARGS(ARGSSF, MODE, TYPE, PRETEND, SECOND) \ |
| do \ |
| { \ |
| if ((ARGSSF).regs < (CRIS_MAX_ARGS_IN_REGS)) \ |
| (PRETEND) = ((CRIS_MAX_ARGS_IN_REGS) - (ARGSSF).regs) * 4; \ |
| if (TARGET_PDEBUG) \ |
| { \ |
| fprintf (asm_out_file, \ |
| "\n; VA:: ANSI: %d args before, anon @ #%d, %dtime\n", \ |
| (ARGSSF).regs, PRETEND, SECOND); \ |
| } \ |
| } \ |
| while (0) |
| |
| /* FIXME: This and other EXPAND_BUILTIN_VA_... target macros are not |
| documented, although used by several targets. */ |
| #define EXPAND_BUILTIN_VA_ARG(VALIST, TYPE) \ |
| cris_expand_builtin_va_arg (VALIST, TYPE) |
| |
| |
| /* Node: Trampolines */ |
| |
| /* This looks too complicated, and it is. I assigned r7 to be the |
| static chain register, but it is call-saved, so we have to save it, |
| and come back to restore it after the call, so we have to save srp... |
| Anyway, trampolines are rare enough that we can cope with this |
| somewhat lack of elegance. |
| (Do not be tempted to "straighten up" whitespace in the asms; the |
| assembler #NO_APP state mandates strict spacing). */ |
| #define TRAMPOLINE_TEMPLATE(FILE) \ |
| do \ |
| { \ |
| fprintf (FILE, "\tmove.d $%s,[$pc+20]\n", \ |
| reg_names[STATIC_CHAIN_REGNUM]); \ |
| fprintf (FILE, "\tmove $srp,[$pc+22]\n"); \ |
| fprintf (FILE, "\tmove.d 0,$%s\n", \ |
| reg_names[STATIC_CHAIN_REGNUM]); \ |
| fprintf (FILE, "\tjsr 0\n"); \ |
| fprintf (FILE, "\tmove.d 0,$%s\n", \ |
| reg_names[STATIC_CHAIN_REGNUM]); \ |
| fprintf (FILE, "\tjump 0\n"); \ |
| } \ |
| while (0) |
| |
| #define TRAMPOLINE_SIZE 32 |
| |
| /* CRIS wants instructions on word-boundary. |
| Note that due to a bug (reported) in 2.7.2 and earlier, this is |
| actually treated as alignment in _bytes_, not _bits_. (Obviously |
| this is not fatal, only a slight waste of stack space). */ |
| #define TRAMPOLINE_ALIGNMENT 16 |
| |
| #define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ |
| do \ |
| { \ |
| emit_move_insn (gen_rtx (MEM, SImode, \ |
| plus_constant (TRAMP, 10)), \ |
| CXT); \ |
| emit_move_insn (gen_rtx (MEM, SImode, \ |
| plus_constant (TRAMP, 16)), \ |
| FNADDR); \ |
| } \ |
| while (0) |
| |
| /* Note that there is no need to do anything with the cache for sake of |
| a trampoline. */ |
| |
| |
| /* Node: Library Calls */ |
| |
| /* If you change this, you have to check whatever libraries and systems |
| that use it. */ |
| #define TARGET_EDOM 33 |
| |
| |
| /* Node: Addressing Modes */ |
| |
| #define HAVE_POST_INCREMENT 1 |
| |
| #define CONSTANT_ADDRESS_P(X) CONSTANT_P (X) |
| |
| #define MAX_REGS_PER_ADDRESS 2 |
| |
| /* There are helper macros defined here which are used only in |
| GO_IF_LEGITIMATE_ADDRESS. |
| |
| Note that you *have to* reject invalid addressing modes for mode |
| MODE, even if it is legal for normal addressing modes. You cannot |
| rely on the constraints to do this work. They can only be used to |
| doublecheck your intentions. One example is that you HAVE TO reject |
| (mem:DI (plus:SI (reg:SI x) (reg:SI y))) because for some reason |
| this cannot be reloaded. (Which of course you can argue that gcc |
| should have done.) FIXME: Strange. Check. */ |
| |
| /* No symbol can be used as an index (or more correct, as a base) together |
| with a register with PIC; the PIC register must be there. */ |
| #define CONSTANT_INDEX_P(X) \ |
| (CONSTANT_P (X) && !(flag_pic && cris_symbol (X))) |
| |
| /* True if X is a valid base register. */ |
| #define BASE_P(X) \ |
| (REG_P (X) && REG_OK_FOR_BASE_P (X)) |
| |
| /* True if X is a valid base register with or without autoincrement. */ |
| #define BASE_OR_AUTOINCR_P(X) \ |
| (BASE_P (X) || (GET_CODE (X) == POST_INC && BASE_P (XEXP (X, 0)))) |
| |
| /* True if X is a valid (register) index for BDAP, i.e. [Rs].S or [Rs+].S. */ |
| #define BDAP_INDEX_P(X) \ |
| ((GET_CODE (X) == MEM && GET_MODE (X) == SImode \ |
| && BASE_OR_AUTOINCR_P (XEXP (X, 0))) \ |
| || (GET_CODE (X) == SIGN_EXTEND \ |
| && GET_CODE (XEXP (X, 0)) == MEM \ |
| && (GET_MODE (XEXP (X, 0)) == HImode \ |
| || GET_MODE (XEXP (X, 0)) == QImode) \ |
| && BASE_OR_AUTOINCR_P (XEXP (XEXP (X, 0), 0)))) |
| |
| /* True if X is a valid (register) index for BIAP, i.e. Rd.m. */ |
| #define BIAP_INDEX_P(X) \ |
| ((BASE_P (X) && REG_OK_FOR_INDEX_P (X)) \ |
| || (GET_CODE (X) == MULT \ |
| && BASE_P (XEXP (X, 0)) \ |
| && REG_OK_FOR_INDEX_P (XEXP (X, 0)) \ |
| && GET_CODE (XEXP (X, 1)) == CONST_INT \ |
| && (INTVAL (XEXP (X, 1)) == 2 \ |
| || INTVAL (XEXP (X, 1)) == 4))) |
| |
| /* True if X is an address that doesn't need a prefix i.e. [Rs] or [Rs+]. */ |
| #define SIMPLE_ADDRESS_P(X) \ |
| (BASE_P (X) \ |
| || (GET_CODE (X) == POST_INC \ |
| && BASE_P (XEXP (X, 0)))) |
| |
| /* A PIC operand looks like a normal symbol here. At output we dress it |
| in "[rPIC+symbol:GOT]" (global symbol) or "rPIC+symbol:GOTOFF" (local |
| symbol) so we exclude all addressing modes where we can't replace a |
| plain "symbol" with that. A global PIC symbol does not fit anywhere |
| here (but is thankfully a general_operand in itself). A local PIC |
| symbol is valid for the plain "symbol + offset" case. */ |
| #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ |
| { \ |
| rtx x1, x2; \ |
| if (SIMPLE_ADDRESS_P (X)) \ |
| goto ADDR; \ |
| if (CONSTANT_P (X) \ |
| && (! flag_pic \ |
| || cris_gotless_symbol (X) \ |
| || ! cris_symbol (X))) \ |
| goto ADDR; \ |
| /* Indexed? */ \ |
| if (GET_CODE (X) == PLUS) \ |
| { \ |
| x1 = XEXP (X, 0); \ |
| x2 = XEXP (X, 1); \ |
| /* BDAP o, Rd. */ \ |
| if ((BASE_P (x1) && CONSTANT_INDEX_P (x2)) \ |
| || (BASE_P (x2) && CONSTANT_INDEX_P (x1)) \ |
| /* BDAP Rs[+], Rd. */ \ |
| || (GET_MODE_SIZE (MODE) <= UNITS_PER_WORD \ |
| && ((BASE_P (x1) && BDAP_INDEX_P (x2)) \ |
| || (BASE_P (x2) && BDAP_INDEX_P (x1)) \ |
| /* BIAP.m Rs, Rd */ \ |
| || (BASE_P (x1) && BIAP_INDEX_P (x2)) \ |
| || (BASE_P (x2) && BIAP_INDEX_P (x1))))) \ |
| goto ADDR; \ |
| } \ |
| else if (GET_CODE (X) == MEM) \ |
| { \ |
| /* DIP (Rs). Reject [[reg+]] and [[reg]] for \ |
| DImode (long long). */ \ |
| if (GET_MODE_SIZE (MODE) <= UNITS_PER_WORD \ |
| && (BASE_P (XEXP (X, 0)) \ |
| || BASE_OR_AUTOINCR_P (XEXP (X, 0)))) \ |
| goto ADDR; \ |
| } \ |
| } |
| |
| #ifndef REG_OK_STRICT |
| /* Nonzero if X is a hard reg that can be used as a base reg |
| or if it is a pseudo reg. */ |
| # define REG_OK_FOR_BASE_P(X) \ |
| (REGNO (X) <= CRIS_LAST_GENERAL_REGISTER \ |
| || REGNO (X) == ARG_POINTER_REGNUM \ |
| || REGNO (X) >= FIRST_PSEUDO_REGISTER) |
| #else |
| /* Nonzero if X is a hard reg that can be used as a base reg. */ |
| # define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) |
| #endif |
| |
| #ifndef REG_OK_STRICT |
| /* Nonzero if X is a hard reg that can be used as an index |
| or if it is a pseudo reg. */ |
| # define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_BASE_P (X) |
| #else |
| /* Nonzero if X is a hard reg that can be used as an index. */ |
| # define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) |
| #endif |
| |
| /* For now, don't do anything. GCC does a good job most often. |
| |
| Maybe we could do something about gcc:s misbehavior when it |
| recalculates frame offsets for local variables, from fp+offs to |
| sp+offs. The resulting address expression gets screwed up |
| sometimes, but I'm not sure that it may be fixed here, since it is |
| already split up in several instructions (Is this still true?). |
| FIXME: Check and adjust for gcc-2.9x. */ |
| #define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) {} |
| |
| /* Kludge to solve Axis-990219: Work around imperfection in |
| reload_load_address1: |
| (plus (sign_extend (mem:qi (reg))) (reg)) |
| should be reloaded as (plus (reg) (reg)), not |
| (plus (sign_extend (reg)) (reg)). |
| There are no checks that reload_load_address_1 "reloads" |
| addresses correctly, so invalidness is not caught or |
| corrected. |
| When the right thing happens in reload, the kludge can |
| be removed; still not as of 2003-02-27. */ |
| |
| #define LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND_LEVELS, WIN) \ |
| do \ |
| { \ |
| if (GET_CODE (X) == PLUS \ |
| && REG_P (XEXP (X, 1)) \ |
| && GET_CODE (XEXP (X, 0)) == SIGN_EXTEND \ |
| && GET_CODE (XEXP (XEXP (X, 0), 0)) == MEM \ |
| && (GET_MODE (XEXP (XEXP (X, 0), 0)) == HImode \ |
| || GET_MODE (XEXP (XEXP (X, 0), 0)) == QImode) \ |
| && (REG_P (XEXP (XEXP (XEXP (X, 0), 0), 0)) \ |
| || (GET_CODE (XEXP (XEXP (XEXP (X, 0), 0), 0)) \ |
| == POST_INC \ |
| && REG_P (XEXP (XEXP (XEXP (XEXP (X, 0), 0), 0), \ |
| 0))))) \ |
| { \ |
| int something_reloaded = 0; \ |
| \ |
| if (REGNO (XEXP (X, 1)) >= FIRST_PSEUDO_REGISTER) \ |
| { \ |
| /* Second reg is pseudo, reload it. */ \ |
| push_reload (XEXP (X, 1), NULL_RTX, &XEXP (X, 1), \ |
| NULL, \ |
| GENERAL_REGS, GET_MODE (X), VOIDmode, 0, 0, \ |
| OPNUM, TYPE); \ |
| something_reloaded = 1; \ |
| } \ |
| \ |
| if (REG_P (XEXP (XEXP (XEXP (X, 0), 0), 0)) \ |
| && (REGNO (XEXP (XEXP (XEXP (X, 0), 0), 0)) \ |
| >= FIRST_PSEUDO_REGISTER)) \ |
| { \ |
| /* First one is a pseudo - reload that. */ \ |
| push_reload (XEXP (XEXP (XEXP (X, 0), 0), 0), NULL_RTX, \ |
| &XEXP (XEXP (XEXP (X, 0), 0), 0), NULL, \ |
| GENERAL_REGS, \ |
| GET_MODE (X), VOIDmode, 0, 0, OPNUM, TYPE); \ |
| something_reloaded = 1; \ |
| } \ |
| \ |
| if (! something_reloaded \ |
| || (GET_CODE (XEXP (XEXP (X, 0), 0)) == POST_INC \ |
| && (REGNO (XEXP (XEXP (XEXP (X, 0), 0), 0)) \ |
| >= FIRST_PSEUDO_REGISTER))) \ |
| /* Reload the sign_extend. Happens if neither reg is a \ |
| pseudo, or the first one was inside post_increment. */ \ |
| push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL, \ |
| GENERAL_REGS, GET_MODE (X), VOIDmode, 0, 0, \ |
| OPNUM, TYPE); \ |
| goto WIN; \ |
| } \ |
| } \ |
| while (0) |
| |
| /* In CRIS, only the postincrement address mode depends thus, |
| since the increment depends on the size of the operand. */ |
| #define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \ |
| do \ |
| { \ |
| if (GET_CODE (ADDR) == POST_INC) \ |
| goto LABEL; \ |
| } \ |
| while (0) |
| |
| #define LEGITIMATE_CONSTANT_P(X) 1 |
| |
| |
| /* Node: Condition Code */ |
| |
| #define NOTICE_UPDATE_CC(EXP, INSN) cris_notice_update_cc (EXP, INSN) |
| |
| /* FIXME: Maybe define CANONICALIZE_COMPARISON later, when playing with |
| optimizations. It is needed; currently we do this with instruction |
| patterns and NOTICE_UPDATE_CC. */ |
| |
| |
| /* Node: Costs */ |
| |
| /* FIXME: Need to define REGISTER_MOVE_COST when more register classes are |
| introduced. */ |
| |
| /* This isn't strictly correct for v0..3 in buswidth-8bit mode, but |
| should suffice. */ |
| #define MEMORY_MOVE_COST(M, CLASS, IN) \ |
| (((M) == QImode) ? 4 : ((M) == HImode) ? 4 : 6) |
| |
| /* Regardless of the presence of delay slots, the default value of 1 for |
| BRANCH_COST is the best in the range (1, 2, 3), tested with gcc-2.7.2 |
| with testcases ipps and gcc, giving smallest and fastest code. */ |
| |
| #define SLOW_BYTE_ACCESS 0 |
| |
| /* This is the threshold *below* which inline move sequences of |
| word-length sizes will be emitted. The "9" will translate to |
| (9 - 1) * 4 = 32 bytes maximum moved, but using 16 instructions |
| (8 instruction sequences) or less. */ |
| #define MOVE_RATIO 9 |
| |
| |
| /* Node: Sections */ |
| |
| #define TEXT_SECTION_ASM_OP "\t.text" |
| |
| #define DATA_SECTION_ASM_OP "\t.data" |
| |
| #define FORCE_EH_FRAME_INFO_IN_DATA_SECTION (! TARGET_ELF) |
| |
| /* The jump table is immediately connected to the preceding insn. */ |
| #define JUMP_TABLES_IN_TEXT_SECTION 1 |
| |
| /* We pull a little trick to register the _fini function with atexit, |
| after (presumably) registering the eh frame info, since we don't handle |
| _fini (a.k.a. ___fini_start) in crt0 or have a crti for "pure" ELF. If |
| you change this, don't forget that you can't have library function |
| references (e.g. to atexit) in crtend.o, since those won't be resolved |
| to libraries; those are linked in *before* crtend.o. */ |
| #ifdef CRT_BEGIN |
| # define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \ |
| static void __attribute__((__used__)) \ |
| call_ ## FUNC (void) \ |
| { \ |
| asm (SECTION_OP); \ |
| FUNC (); \ |
| if (__builtin_strcmp (#FUNC, "frame_dummy") == 0) \ |
| { \ |
| extern void __fini__start (void); \ |
| atexit (__fini__start); \ |
| } \ |
| asm (TEXT_SECTION_ASM_OP); \ |
| } |
| #endif |
| |
| /* Node: PIC */ |
| |
| #define PIC_OFFSET_TABLE_REGNUM (flag_pic ? 0 : INVALID_REGNUM) |
| |
| #define LEGITIMATE_PIC_OPERAND_P(X) cris_legitimate_pic_operand (X) |
| |
| |
| /* Node: File Framework */ |
| |
| /* We don't want an .ident for gcc. To avoid that but still support |
| #ident, we override ASM_OUTPUT_IDENT and, since the gcc .ident is its |
| only use besides ASM_OUTPUT_IDENT, undef IDENT_ASM_OP from elfos.h. */ |
| #undef IDENT_ASM_OP |
| #undef ASM_OUTPUT_IDENT |
| #define ASM_OUTPUT_IDENT(FILE, NAME) \ |
| fprintf (FILE, "%s\"%s\"\n", "\t.ident\t", NAME); |
| |
| #define ASM_APP_ON "#APP\n" |
| |
| #define ASM_APP_OFF "#NO_APP\n" |
| |
| |
| /* Node: Data Output */ |
| |
| #define IS_ASM_LOGICAL_LINE_SEPARATOR(C) (C) == '@' |
| |
| /* Node: Uninitialized Data */ |
| |
| /* Remember to round off odd values if we want data alignment, |
| since we cannot do that with an .align directive. |
| |
| Using .comm causes the space not to be reserved in .bss, but by |
| tricks with the symbol type. Not good if other tools than binutils |
| are used on the object files. Since ".global ... .lcomm ..." works, we |
| use that. Use .._ALIGNED_COMMON, since gcc whines when we only have |
| ..._COMMON, and we prefer to whine ourselves; BIGGEST_ALIGNMENT is not |
| the one to check. This done for a.out only. */ |
| /* FIXME: I suspect a bug in gcc with alignment. Do not warn until |
| investigated; it mucks up the testsuite results. */ |
| #define CRIS_ASM_OUTPUT_ALIGNED_DECL_COMMON(FILE, DECL, NAME, SIZE, ALIGN, LOCAL) \ |
| do \ |
| { \ |
| int align_ = (ALIGN) / BITS_PER_UNIT; \ |
| if (TARGET_DATA_ALIGN && TARGET_ALIGN_BY_32 && align_ < 4) \ |
| align_ = 4; \ |
| else if (TARGET_DATA_ALIGN && align_ < 2) \ |
| align_ = 2; \ |
| /* FIXME: Do we need this? */ \ |
| else if (align_ < 1) \ |
| align_ = 1; \ |
| \ |
| if (TARGET_ELF) \ |
| { \ |
| if (LOCAL) \ |
| { \ |
| fprintf ((FILE), "%s", LOCAL_ASM_OP); \ |
| assemble_name ((FILE), (NAME)); \ |
| fprintf ((FILE), "\n"); \ |
| } \ |
| fprintf ((FILE), "%s", COMMON_ASM_OP); \ |
| assemble_name ((FILE), (NAME)); \ |
| fprintf ((FILE), ",%u,%u\n", (int)(SIZE), align_); \ |
| } \ |
| else \ |
| { \ |
| /* We can't tell a one-only or weak COMM from a "global \ |
| COMM" so just make all non-locals weak. */ \ |
| if (! (LOCAL)) \ |
| ASM_WEAKEN_LABEL (FILE, NAME); \ |
| fputs ("\t.lcomm ", (FILE)); \ |
| assemble_name ((FILE), (NAME)); \ |
| fprintf ((FILE), ",%u\n", \ |
| ((int)(SIZE) + (align_ - 1)) & ~(align_ - 1)); \ |
| } \ |
| } \ |
| while (0) |
| |
| #define ASM_OUTPUT_ALIGNED_DECL_COMMON(FILE, DECL, NAME, SIZE, ALIGN) \ |
| CRIS_ASM_OUTPUT_ALIGNED_DECL_COMMON(FILE, DECL, NAME, SIZE, ALIGN, 0) |
| |
| #undef ASM_OUTPUT_ALIGNED_DECL_LOCAL |
| #define ASM_OUTPUT_ALIGNED_DECL_LOCAL(FILE, DECL, NAME, SIZE, ALIGN) \ |
| CRIS_ASM_OUTPUT_ALIGNED_DECL_COMMON(FILE, DECL, NAME, SIZE, ALIGN, 1) |
| |
| /* FIXME: define ASM_OUTPUT_SHARED_COMMON and emit an error when it is |
| used with -melinux and a.out. */ |
| |
| /* Node: Label Output */ |
| |
| /* Globalizing directive for a label. */ |
| #define GLOBAL_ASM_OP "\t.global " |
| |
| #define SUPPORTS_WEAK 1 |
| |
| /* Remove any previous definition (elfos.h). */ |
| #undef ASM_GENERATE_INTERNAL_LABEL |
| #define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \ |
| sprintf (LABEL, "*%s%s%ld", LOCAL_LABEL_PREFIX, PREFIX, (long) NUM) |
| |
| /* Node: Initialization */ |
| /* (no definitions) */ |
| |
| /* Node: Macros for Initialization */ |
| /* (no definitions) */ |
| |
| /* Node: Instruction Output */ |
| |
| #define REGISTER_NAMES \ |
| {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", \ |
| "r9", "r10", "r11", "r12", "r13", "sp", "pc", "srp", "faked_ap"} |
| |
| #define ADDITIONAL_REGISTER_NAMES \ |
| {{"r14", 14}, {"r15", 15}} |
| |
| #define PRINT_OPERAND(FILE, X, CODE) \ |
| cris_print_operand (FILE, X, CODE) |
| |
| /* For delay-slot handling. */ |
| #define PRINT_OPERAND_PUNCT_VALID_P(CODE) \ |
| ((CODE) == '#' || (CODE) == '!') |
| |
| #define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ |
| cris_print_operand_address (FILE, ADDR) |
| |
| /* Output an empty line to illustrate the presence of the delay slot. */ |
| #define DBR_OUTPUT_SEQEND(FILE) \ |
| fprintf (FILE, "\n") |
| |
| #define LOCAL_LABEL_PREFIX (TARGET_ELF ? "." : "") |
| |
| /* cppinit.c initializes a const array from this, so it must be constant, |
| can't have it different based on options. Luckily, the prefix is |
| always allowed, so let's have it on all GCC-generated code. Note that |
| we have this verbatim everywhere in the back-end, not using %R or %s or |
| such. */ |
| #define REGISTER_PREFIX "$" |
| |
| /* Remove any previous definition (elfos.h). */ |
| /* We use -fno-leading-underscore to remove it, when necessary. */ |
| #undef USER_LABEL_PREFIX |
| #define USER_LABEL_PREFIX "_" |
| |
| #define ASM_OUTPUT_REG_PUSH(FILE, REGNO) \ |
| fprintf (FILE, "\tpush $%s\n", reg_names[REGNO]) |
| |
| #define ASM_OUTPUT_REG_POP(FILE, REGNO) \ |
| fprintf (FILE, "\tpop $%s\n", reg_names[REGNO]) |
| |
| |
| /* Node: Dispatch Tables */ |
| |
| #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ |
| asm_fprintf (FILE, "\t.word %LL%d-%LL%d\n", VALUE, REL) |
| |
| #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ |
| asm_fprintf (FILE, "\t.dword %LL%d\n", VALUE) |
| |
| /* Defined to also emit an .align in elfos.h. We don't want that. */ |
| #undef ASM_OUTPUT_CASE_LABEL |
| |
| /* Since the "bound" insn loads the comparison value if the compared< |
| value (register) is out of bounds (0..comparison value-1), we need |
| to output another case to catch it. |
| The way to find it is to look for the label_ref at the else-arm inside |
| the expanded casesi core-insn. |
| FIXME: Check this construct when changing to new version of gcc. */ |
| #define ASM_OUTPUT_CASE_END(STREAM, NUM, TABLE) \ |
| do \ |
| { \ |
| asm_fprintf (STREAM, "\t.word %LL%d-%LL%d%s\n", \ |
| CODE_LABEL_NUMBER \ |
| (XEXP (XEXP (XEXP \ |
| (XVECEXP \ |
| (PATTERN (PREV_INSN (PREV_INSN \ |
| (TABLE))), \ |
| 0, 0), 1), 2), 0)), \ |
| NUM, \ |
| (TARGET_PDEBUG ? "; default" : "")); \ |
| } \ |
| while (0) |
| |
| |
| /* Node: Exception Region Output */ |
| /* (no definitions) */ |
| /* FIXME: Fill in with our own optimized layout. */ |
| |
| /* Node: Alignment Output */ |
| |
| #define ASM_OUTPUT_ALIGN(FILE, LOG) \ |
| fprintf (FILE, "\t.align %d\n", (LOG)) |
| |
| |
| /* Node: All Debuggers */ |
| |
| #define DBX_REGISTER_NUMBER(REGNO) \ |
| ((REGNO) == CRIS_SRP_REGNUM ? CRIS_CANONICAL_SRP_REGNUM : (REGNO)) |
| |
| /* FIXME: Investigate DEBUGGER_AUTO_OFFSET, DEBUGGER_ARG_OFFSET. */ |
| |
| |
| /* Node: DBX Options */ |
| |
| /* Is this correct? Check later. */ |
| #define DBX_NO_XREFS |
| |
| #define DBX_CONTIN_LENGTH 0 |
| |
| /* FIXME: Is this needed when we have 0 DBX_CONTIN_LENGTH? */ |
| #define DBX_CONTIN_CHAR '?' |
| |
| |
| /* Node: DBX Hooks */ |
| /* (no definitions) */ |
| |
| /* Node: File names and DBX */ |
| /* (no definitions) */ |
| |
| |
| /* Node: SDB and DWARF */ |
| /* (no definitions) */ |
| |
| /* Node: Misc */ |
| |
| /* FIXME: Check this one more time. */ |
| #define PREDICATE_CODES \ |
| {"cris_orthogonal_operator", \ |
| {PLUS, MINUS, IOR, AND, UMIN}}, \ |
| {"cris_commutative_orth_op", \ |
| {PLUS, IOR, AND, UMIN}}, \ |
| {"cris_operand_extend_operator", \ |
| {PLUS, MINUS, UMIN}}, \ |
| {"cris_additive_operand_extend_operator", \ |
| {PLUS, MINUS}}, \ |
| {"cris_extend_operator", \ |
| {ZERO_EXTEND, SIGN_EXTEND}}, \ |
| {"cris_plus_or_bound_operator", \ |
| {PLUS, UMIN}}, \ |
| {"cris_mem_op", \ |
| {MEM}}, \ |
| {"cris_bdap_operand", \ |
| {SUBREG, REG, LABEL_REF, SYMBOL_REF, MEM, CONST_INT, \ |
| CONST_DOUBLE, CONST, SIGN_EXTEND}}, \ |
| {"cris_bdap_biap_operand", \ |
| {SUBREG, REG, LABEL_REF, SYMBOL_REF, MEM, CONST_INT, \ |
| CONST_DOUBLE, CONST, SIGN_EXTEND, MULT}}, \ |
| {"cris_general_operand_or_gotless_symbol", \ |
| {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \ |
| LABEL_REF, SUBREG, REG, MEM}}, \ |
| {"cris_general_operand_or_symbol", \ |
| {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \ |
| LABEL_REF, SUBREG, REG, MEM}}, \ |
| {"cris_general_operand_or_plt_symbol", \ |
| {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \ |
| LABEL_REF, SUBREG, REG, MEM}}, \ |
| {"cris_mem_call_operand", \ |
| {MEM}}, |
| |
| /* A combination of the bound (umin) insn together with a |
| sign-extended add via the table to PC seems optimal. |
| If the table overflows, the assembler will take care of it. |
| Theoretically, in extreme cases (uncertain if they occur), an error |
| will be emitted, so FIXME: Check how large case-tables are emitted, |
| possible add an option to emit SImode case-tables. */ |
| #define CASE_VECTOR_MODE HImode |
| |
| #define CASE_VECTOR_PC_RELATIVE 1 |
| |
| /* FIXME: Investigate CASE_VECTOR_SHORTEN_MODE to make sure HImode is not |
| used when broken-.word could possibly fail (plus testcase). */ |
| |
| #define FIXUNS_TRUNC_LIKE_FIX_TRUNC |
| |
| /* This is the number of bytes that can be moved in one |
| reasonably fast instruction sequence. For CRIS, this is two |
| instructions: mem => reg, reg => mem. */ |
| #define MOVE_MAX 4 |
| |
| /* Maybe SHIFT_COUNT_TRUNCATED is safe to define? FIXME: Check later. */ |
| |
| #define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 |
| |
| #define Pmode SImode |
| |
| #define FUNCTION_MODE QImode |
| |
| #define NO_IMPLICIT_EXTERN_C |
| |
| /* |
| * Local variables: |
| * eval: (c-set-style "gnu") |
| * indent-tabs-mode: t |
| * End: |
| */ |