diff options
author | Kazuhiro Inaoka <inaoka.kazuhiro@renesas.com> | 2003-12-31 10:33:02 +0000 |
---|---|---|
committer | Nick Clifton <nickc@gcc.gnu.org> | 2003-12-31 10:33:02 +0000 |
commit | ad12652102049de3b337a2e17718e6ca9810a159 (patch) | |
tree | 7a7665a0fcdb8294179c40f5b2418efd4aa141dc /gcc | |
parent | 04d1e6e212868d75be10537dba11d3a019dc93e1 (diff) | |
download | gcc-ad12652102049de3b337a2e17718e6ca9810a159.zip gcc-ad12652102049de3b337a2e17718e6ca9810a159.tar.gz gcc-ad12652102049de3b337a2e17718e6ca9810a159.tar.bz2 |
Add support for m32r-linux target.
From-SVN: r75263
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 38 | ||||
-rw-r--r-- | gcc/config.gcc | 28 | ||||
-rw-r--r-- | gcc/config/m32r/linux.h | 104 | ||||
-rw-r--r-- | gcc/config/m32r/little.h | 34 | ||||
-rw-r--r-- | gcc/config/m32r/m32r-protos.h | 32 | ||||
-rw-r--r-- | gcc/config/m32r/m32r.c | 180 | ||||
-rw-r--r-- | gcc/config/m32r/m32r.h | 536 | ||||
-rw-r--r-- | gcc/config/m32r/m32r.md | 160 | ||||
-rw-r--r-- | gcc/config/m32r/t-linux | 42 | ||||
-rw-r--r-- | gcc/config/m32r/xm-linux.h | 26 | ||||
-rw-r--r-- | gcc/config/m32r/xm-m32r.h | 43 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 67 |
12 files changed, 1009 insertions, 281 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f25022b..1aa9d98 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,41 @@ +2003-12-31 Kazuhiro Inaoka <inaoka.kazuhiro@renesas.com> + + * config.gcc: Added m32r-linux m32rle-elf and m32le-linux targets. + * doc/invoke.texi: Document -mflush-func, -mflush-trap options. + Also add documentation for -mdebug, -malign-loops, -missue-rate, + and -mbranch-cost options. + * config/m32r/t-linux: New file: m32r-linux support. + * config/m32r/xm-linux.h: Likewise. + * config/m32r/xm-m32r.h: Likewise. + * config/m32r/linux.h: Likewise. + * config/m32r/little.h: New file: Little endian code generation + support. + * config/m32r/m32r-protos.h (m32r_legitimize_pic_address, + m32r_legitimate_pic_operand_p, load_pic_register): Add + prototypes. + * config/m32r/m32r.c (m32r_init): Add options for cache-flush. + (addr24_operand): Changes for PIC code generation. + * config/m32r/m32r.h (LABEL_ALIGN): Define to calculate PNOP + length at labels. + (ASM_SPEC): Add PIC support. + (FUNCTION_PROFILER): New define. + (TRAMPOLINE_SIZE, INITIALIZE_TRAMPOLINE): Changed to support + trampoline. + (CONDITIONAL_REGISTER_USAGE, CONSTANT_ADDRESS_P, + LEGITIMIZE_ADDRESS, JUMP_TABLES_IN_TEXT_SECTION, + PIC_OFFSET_TABLE_REGNUM, FINALIZE_PIC, LEGITIMATE_PIC_OPERAND_P, + ASM_OUTPUT_ADDR_DIFF_ELT, CASE_VECTOR_MODE): Define for PIC. + (move_src_operand, m32r_compute_frame_size, m32r_expand_prologue, + m32r_finalize_pic): Changes for PIC and profile support. + (global_offset_table, load_pic_register, m32r_legitimate_pic_operand_p, + m32r_legitimize_pic_address): Add for PIC support. + (m32r_file_start): Changed for little-endian-target. + * config/m32r/m32r.md (mvqi, movhi, movsi, movdi, movsf, movdf, + tablejump, tablejump_insn, call, call_value, call_value_via_label): + Changes for PIC. + (pic_load_addr, get_pc, builtin_setjmp_receiver): Added for PIC. + (flush_icache): Changes for cache-flush trap. + 2003-12-30 Kazu Hirata <kazu@cs.umass.edu> * config/i386/i386.h: Remove an unnecessary #undef. diff --git a/gcc/config.gcc b/gcc/config.gcc index 168a235..b4e750a 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -279,6 +279,9 @@ ia64-*-*) hppa*-*-* | parisc*-*-*) cpu_type=pa ;; +m32r*-*-*) + cpu_type=m32r + ;; m680[012]0-*-*) cpu_type=m68k extra_headers=math-68881.h @@ -1279,6 +1282,31 @@ m32r-*-elf*) extra_parts="crtinit.o crtfini.o" use_fixproto=yes ;; +m32rle-*-elf*) + tm_file="dbxelf.h elfos.h svr4.h m32r/little.h ${tm_file}" + extra_parts="crtinit.o crtfini.o m32rx/crtinit.o m32rx/crtfini.o" + use_fixproto=yes + ;; +m32r-*-linux*) + tm_file="dbxelf.h elfos.h svr4.h linux.h ${tm_file} m32r/linux.h" + extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o" + tmake_file="m32r/t-linux" + gnu_ld=yes + use_fixproto=yes + if test x$enable_threads = xyes; then + thread_file='posix' + fi + ;; +m32rle-*-linux*) + tm_file="dbxelf.h elfos.h svr4.h linux.h m32r/little.h ${tm_file} m32r/linux.h" + extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o" + tmake_file="m32r/t-linux" + gnu_ld=yes + use_fixproto=yes + if test x$enable_threads = xyes; then + thread_file='posix' + fi + ;; # m68hc11 and m68hc12 share the same machine description. m68hc11-*-*|m6811-*-*) tm_file="dbxelf.h elfos.h m68hc11/m68hc11.h" diff --git a/gcc/config/m32r/linux.h b/gcc/config/m32r/linux.h new file mode 100644 index 0000000..b7da5bf --- /dev/null +++ b/gcc/config/m32r/linux.h @@ -0,0 +1,104 @@ +/* Definitions for Renesas M32R running Linux-based GNU systems using ELF. + Copyright (C) 2003 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING. If not, write to the + Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. */ + +#define LINUX_DEFAULT_ELF + +/* A lie, I guess, but the general idea behind linux/ELF is that we are + supposed to be outputting something that will assemble under SVr4. + This gets us pretty close. */ + +#define HANDLE_SYSV_PRAGMA + +#undef HANDLE_PRAGMA_PACK + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (M32R GNU/Linux with ELF)"); + +#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 + +/* Provide a LINK_SPEC appropriate for Linux. Here we provide support + for the special GCC options -static and -shared, which allow us to + link things in one of these three modes by applying the appropriate + combinations of options at link-time. We like to support here for + as many of the other GNU linker options as possible. But I don't + have the time to search for those flags. I am sure how to add + support for -soname shared_object_name. H.J. + + I took out %{v:%{!V:-V}}. It is too much :-(. They can use + -Wl,-V. + + When the -shared link option is used a final link is not being + done. */ + +/* If ELF is the default format, we should not use /lib/elf. */ + +#undef LINK_SPEC +#if TARGET_LITTLE_ENDIAN +#define LINK_SPEC "%(link_cpu) -m m32rlelf_linux %{shared:-shared} \ + %{!shared: \ + %{!ibcs: \ + %{!static: \ + %{rdynamic:-export-dynamic} \ + %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \ + %{static:-static}}}" +#else +#define LINK_SPEC "%(link_cpu) -m m32relf_linux %{shared:-shared} \ + %{!shared: \ + %{!ibcs: \ + %{!static: \ + %{rdynamic:-export-dynamic} \ + %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \ + %{static:-static}}}" +#endif + +#undef LIB_SPEC +#define LIB_SPEC \ + "%{shared: -lc} \ + %{!shared: %{mieee-fp:-lieee} %{pthread:-lpthread} \ + %{profile:-lc_p} %{!profile: -lc}}" + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC \ + "%{!shared: \ + %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}}\ + crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC \ + "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s" + +#undef SUBTARGET_CPP_SPEC +#define SUBTARGET_CPP_SPEC "\ + %{posix:-D_POSIX_SOURCE} \ + %{pthread:-D_REENTRANT -D_PTHREADS} \ +" + +#define TARGET_OS_CPP_BUILTINS() LINUX_TARGET_OS_CPP_BUILTINS() + diff --git a/gcc/config/m32r/little.h b/gcc/config/m32r/little.h new file mode 100644 index 0000000..793cf24 --- /dev/null +++ b/gcc/config/m32r/little.h @@ -0,0 +1,34 @@ +/* Definitions for Renesas little endian M32R cpu. + Copyright (C) 2003 + Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING. If not, write to the + Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. */ + +#define TARGET_LITTLE_ENDIAN (!TARGET_BIG_ENDIAN) + +#define CPP_ENDIAN_SPEC \ + " %{mbe:-D__BIG_ENDIAN__} %{mbig-endian:-D__BIG_ENDIAN__}" \ + " %{!mbe: %{!mbig-endian:-D__LITTLE_ENDIAN__}}" + +#define CC1_ENDIAN_SPEC " %{!mbe: %{!mbig-endian:-mle}}" + +#define ASM_ENDIAN_SPEC \ + " %{!mbe: %{!mbig-endian:-EL}} %{mbe:-EB} %{mbig-endian:-EB}" + +#define LINK_ENDIAN_SPEC " %{!mbe: %{!mbig-endian:-EL}}" + diff --git a/gcc/config/m32r/m32r-protos.h b/gcc/config/m32r/m32r-protos.h index cdd9db3..603c0bd 100644 --- a/gcc/config/m32r/m32r-protos.h +++ b/gcc/config/m32r/m32r-protos.h @@ -1,22 +1,22 @@ /* Prototypes for m32r.c functions used in the md file & elsewhere. - Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. -This file is part of GCC. + 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 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. + 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. */ + 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. */ /* Function prototypes that cannot exist in v850.h due to dependency complications. */ @@ -31,6 +31,8 @@ extern int m32r_first_insn_address (void); extern void m32r_expand_prologue (void); extern void m32r_finalize_pic (void); extern int direct_return (void); +extern void m32r_load_pic_register (void); + #ifdef TREE_CODE extern enum m32r_function_type m32r_compute_function_type (tree); @@ -55,6 +57,8 @@ extern void m32r_print_operand (FILE *, rtx, int); extern void m32r_print_operand_address (FILE *, rtx); extern int m32r_not_same_reg (rtx, rtx); extern int m32r_hard_regno_rename_ok (unsigned int, unsigned int); +extern int m32r_legitimate_pic_operand_p (rtx); +extern rtx m32r_legitimize_pic_address (rtx, rtx); #ifdef HAVE_MACHINE_MODES extern int call_address_operand (rtx, Mmode); diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c index a5a2b26..244264b 100644 --- a/gcc/config/m32r/m32r.c +++ b/gcc/config/m32r/m32r.c @@ -68,6 +68,19 @@ static int m32r_sched_odd_word_p; /* For string literals, etc. */ #define LIT_NAME_P(NAME) ((NAME)[0] == '*' && (NAME)[1] == '.') +/* Cache-flush support. Cache-flush is used at trampoline. + Default cache-flush is "trap 12". + default cache-flush function is "_flush_cache" (CACHE_FLUSH_FUNC) + default cache-flush trap-interrupt number is "12". (CACHE_FLUSH_TRAP) + You can change how to generate code of cache-flush with following options. + -flush-func=FLUSH-FUNC-NAME + -no-flush-func + -fluch-trap=TRAP-NUMBER + -no-flush-trap. */ +const char *m32r_cache_flush_func = CACHE_FLUSH_FUNC; +const char *m32r_cache_flush_trap_string = CACHE_FLUSH_TRAP; +int m32r_cache_flush_trap = 12; + /* Forward declaration. */ static void init_reg_tables (void); static void block_move_call (rtx, rtx, rtx); @@ -166,6 +179,15 @@ m32r_init (void) m32r_sdata = M32R_SDATA_USE; else error ("bad value (%s) for -msdata switch", m32r_sdata_string); + + if (m32r_cache_flush_trap_string) + { + /* Change trap-number (12) for cache-flush to the others (0 - 15). */ + m32r_cache_flush_trap = atoi (m32r_cache_flush_trap_string); + if (m32r_cache_flush_trap < 0 || m32r_cache_flush_trap > 15) + error ("bad value (%s) for -flush-trap=n (0=<n<=15)", + m32r_cache_flush_trap_string); + } } /* Vectors to keep interesting information about registers where it can easily @@ -509,6 +531,9 @@ addr24_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { rtx sym; + if (flag_pic) + return 0; + if (GET_CODE (op) == LABEL_REF) return TARGET_ADDR24; @@ -549,7 +574,8 @@ addr32_operand (rtx op, enum machine_mode mode) else if (GET_CODE (op) == CONST && GET_CODE (XEXP (op, 0)) == PLUS && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF - && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT) + && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT + && ! flag_pic) sym = XEXP (XEXP (op, 0), 0); else return 0; @@ -563,6 +589,9 @@ addr32_operand (rtx op, enum machine_mode mode) int call26_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { + if (flag_pic) + return 0; + if (GET_CODE (op) == SYMBOL_REF) return SYMBOL_REF_MODEL (op) != M32R_MODEL_LARGE; @@ -574,6 +603,9 @@ call26_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) int seth_add3_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { + if (flag_pic) + return 0; + if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF) return 1; @@ -711,6 +743,7 @@ move_src_operand (rtx op, enum machine_mode mode) { switch (GET_CODE (op)) { + case LABEL_REF : case SYMBOL_REF : case CONST : return addr24_operand (op, mode); @@ -726,8 +759,8 @@ move_src_operand (rtx op, enum machine_mode mode) } else return 1; - case LABEL_REF : - return TARGET_ADDR24; + case CONSTANT_P_RTX: + return 1; case CONST_DOUBLE : if (mode == SFmode) return 1; @@ -1801,6 +1834,7 @@ m32r_compute_frame_size (int size) /* # of var. bytes allocated. */ unsigned int gmask; enum m32r_function_type fn_type; int interrupt_p; + int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table); var_size = M32R_STACK_ALIGN (size); args_size = M32R_STACK_ALIGN (current_function_outgoing_args_size); @@ -1818,7 +1852,8 @@ m32r_compute_frame_size (int size) /* # of var. bytes allocated. */ /* Calculate space needed for registers. */ for (regno = 0; regno < M32R_MAX_INT_REGS; regno++) { - if (MUST_SAVE_REGISTER (regno, interrupt_p)) + if (MUST_SAVE_REGISTER (regno, interrupt_p) + || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used)) { reg_size += UNITS_PER_WORD; gmask |= 1 << regno; @@ -1826,7 +1861,7 @@ m32r_compute_frame_size (int size) /* # of var. bytes allocated. */ } current_frame_info.save_fp = MUST_SAVE_FRAME_POINTER; - current_frame_info.save_lr = MUST_SAVE_RETURN_ADDR; + current_frame_info.save_lr = MUST_SAVE_RETURN_ADDR || pic_reg_used; reg_size += ((current_frame_info.save_fp + current_frame_info.save_lr) * UNITS_PER_WORD); @@ -1865,6 +1900,21 @@ m32r_first_insn_address (void) return 0; } +/* The table we use to reference PIC data. */ +static rtx global_offset_table; + +void +m32r_load_pic_register (void) +{ + global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_"); + emit_insn (gen_get_pc (pic_offset_table_rtx, global_offset_table, + gen_rtx_CONST_INT(SImode, TARGET_MODEL_SMALL))); + + /* 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, pic_offset_table_rtx)); +} + /* Expand the m32r prologue as a series of insns. */ void @@ -1873,6 +1923,7 @@ m32r_expand_prologue (void) int regno; int frame_size; unsigned int gmask; + int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table); if (! current_frame_info.initialized) m32r_compute_frame_size (get_frame_size ()); @@ -1935,6 +1986,14 @@ m32r_expand_prologue (void) emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx)); if (current_function_profile) + /* Push lr for mcount (form_pc, x). */ + emit_insn (gen_movsi_push (stack_pointer_rtx, + gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM))); + + if (pic_reg_used) + m32r_load_pic_register (); + + if (current_function_profile && !pic_reg_used) emit_insn (gen_blockage ()); } @@ -2084,18 +2143,122 @@ direct_return (void) if (! current_frame_info.initialized) m32r_compute_frame_size (get_frame_size ()); - return current_frame_info.total_size == 0; + return current_frame_info.total_size == 0; } /* PIC. */ +int +m32r_legitimate_pic_operand_p (rtx x) +{ + if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF) + return 0; + + if (GET_CODE (x) == CONST + && GET_CODE (XEXP (x, 0)) == PLUS + && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF + || GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF) + && (GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)) + return 0; + + return 1; +} + +rtx +m32r_legitimize_pic_address (rtx orig, rtx reg) +{ +#ifdef DEBUG_PIC + printf("m32r_legitimize_pic_address()\n"); +#endif + + if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF) + { + rtx pic_ref, address; + rtx insn; + int subregs = 0; + + if (reg == 0) + { + if (reload_in_progress || reload_completed) + abort (); + else + reg = gen_reg_rtx (Pmode); + + subregs = 1; + } + + if (subregs) + address = gen_reg_rtx (Pmode); + else + address = reg; + + emit_insn (gen_pic_load_addr (address, orig)); + + emit_insn (gen_addsi3 (address, address, pic_offset_table_rtx)); + pic_ref = gen_rtx (MEM, Pmode, address); + + RTX_UNCHANGING_P (pic_ref) = 1; + insn = emit_move_insn (reg, pic_ref); + current_function_uses_pic_offset_table = 1; +#if 0 + /* 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)); +#endif + return reg; + } + else if (GET_CODE (orig) == CONST) + { + rtx base, offset; + + if (GET_CODE (XEXP (orig, 0)) == PLUS + && XEXP (XEXP (orig, 0), 1) == pic_offset_table_rtx) + return orig; + + if (reg == 0) + { + if (reload_in_progress || reload_completed) + abort (); + else + reg = gen_reg_rtx (Pmode); + } + + if (GET_CODE (XEXP (orig, 0)) == PLUS) + { + base = m32r_legitimize_pic_address (XEXP (XEXP (orig, 0), 0), reg); + if (base == reg) + offset = m32r_legitimize_pic_address (XEXP (XEXP (orig, 0), 1), NULL_RTX); + else + offset = m32r_legitimize_pic_address (XEXP (XEXP (orig, 0), 1), reg); + } + else + return orig; + + if (GET_CODE (offset) == CONST_INT) + { + if (INT16_P (INTVAL (offset))) + return plus_constant (base, INTVAL (offset)); + else if (! reload_in_progress && ! reload_completed) + offset = force_reg (Pmode, offset); + else + /* If we reach here, then something is seriously wrong. */ + abort (); + } + + return gen_rtx (PLUS, Pmode, base, offset); + } + + return orig; +} + /* Emit special PIC prologues and epilogues. */ void m32r_finalize_pic (void) { - /* Nothing to do. */ + current_function_uses_pic_offset_table |= current_function_profile; } /* Nested function support. */ @@ -2120,6 +2283,9 @@ m32r_file_start (void) fprintf (asm_out_file, "%s M32R/D special options: -G " HOST_WIDE_INT_PRINT_UNSIGNED "\n", ASM_COMMENT_START, g_switch_value); + + if (TARGET_LITTLE_ENDIAN) + fprintf (asm_out_file, "\t.little\n"); } /* Print operand X (an rtx) in assembler syntax to file FILE. diff --git a/gcc/config/m32r/m32r.h b/gcc/config/m32r/m32r.h index 1ed1f09..0c7ce06 100644 --- a/gcc/config/m32r/m32r.h +++ b/gcc/config/m32r/m32r.h @@ -38,6 +38,9 @@ #undef STARTFILE_SPEC #undef ENDFILE_SPEC #undef SUBTARGET_SWITCHES + +#undef ASM_APP_ON +#undef ASM_APP_OFF /* M32R/X overrides. */ @@ -50,7 +53,6 @@ %{m32r:-U__M32RX__ -U__m32rx__ -U__M32R2__ -U__m32r2__} \ " - /* Assembler switches. */ #define ASM_CPU_SPEC \ "%{m32r} %{m32rx} %{m32r2} %{!O0: %{O*: -O}} --no-warn-explicit-parallel-conflicts" @@ -101,7 +103,7 @@ #define TARGET_VERSION fprintf (stderr, " (m32r)") #endif -/* Switch Recognition by gcc.c. Add -G xx support */ +/* Switch Recognition by gcc.c. Add -G xx support. */ #undef SWITCH_TAKES_ARG #define SWITCH_TAKES_ARG(CHAR) \ @@ -115,6 +117,13 @@ builtin_define ("__M32R__"); \ builtin_assert ("cpu=m32r"); \ builtin_assert ("machine=m32r"); \ + builtin_define (TARGET_BIG_ENDIAN \ + ? "__BIG_ENDIAN__" : "__LITTLE_ENDIAN__"); \ + if (flag_pic) \ + { \ + builtin_define ("__pic__"); \ + builtin_define ("__PIC__"); \ + } \ } \ while (0) @@ -157,7 +166,7 @@ #endif #ifndef RELAX_SPEC -#if 0 /* not supported yet */ +#if 0 /* Not supported yet. */ #define RELAX_SPEC "%{mrelax:-relax}" #else #define RELAX_SPEC "" @@ -174,11 +183,12 @@ { "relax", RELAX_SPEC }, \ SUBTARGET_EXTRA_SPECS +#undef CC1_SPEC #define CC1_SPEC "%{G*} %(cc1_cpu)" /* Options to pass on to the assembler. */ #undef ASM_SPEC -#define ASM_SPEC "%{v} %(asm_cpu) %(relax)" +#define ASM_SPEC "%{v} %(asm_cpu) %(relax) %{fpic:-K PIC} %{fPIC:-K PIC}" #define LINK_SPEC "%{v} %(link_cpu) %(relax)" @@ -234,6 +244,16 @@ extern int target_flags; #undef TARGET_M32R #define TARGET_M32R (! TARGET_M32RX && ! TARGET_M32R2) +/* Big Endian Flag. */ +#define BIG_ENDIAN_BIT (1 << 7) +#define TARGET_BIG_ENDIAN (target_flags & BIG_ENDIAN_BIT) + +/* Little Endian Flag. */ +#define LITTLE_ENDIAN_BIT (1 << 8) +#ifndef TARGET_LITTLE_ENDIAN /* See little.h */ +#define TARGET_LITTLE_ENDIAN (target_flags & LITTLE_ENDIAN_BIT) +#endif + /* Macro to define tables used to set the flags. This is a list in braces of pairs in braces, each pair being { "NAME", VALUE } @@ -270,6 +290,11 @@ extern int target_flags; extern const char * m32r_model_string; extern const char * m32r_sdata_string; +/* Cache-flush support. */ +extern const char * m32r_cache_flush_func; +extern const char * m32r_cache_flush_trap_string; +extern int m32r_cache_flush_trap; + #ifndef SUBTARGET_OPTIONS #define SUBTARGET_OPTIONS #endif @@ -279,7 +304,15 @@ extern const char * m32r_sdata_string; { "model=", & m32r_model_string, \ N_("Code size: small, medium or large"), 0}, \ { "sdata=", & m32r_sdata_string, \ - N_("Small data area: none, sdata, use"), 0} \ + N_("Small data area: none, sdata, use"), 0}, \ + { "no-flush-func", & m32r_cache_flush_func, \ + N_("Don't call any cache flush functions") }, \ + { "flush-func=", & m32r_cache_flush_func, \ + N_("Specify cache flush function") }, \ + { "no-flush-trap", & m32r_cache_flush_trap_string, \ + N_("Don't call any cache flush trap") }, \ + { "flush-trap=", & m32r_cache_flush_trap_string, \ + N_("Specify cache flush trap number") } \ SUBTARGET_OPTIONS \ } @@ -307,13 +340,13 @@ extern const char * m32r_sdata_string; enum m32r_model { M32R_MODEL_SMALL, M32R_MODEL_MEDIUM, M32R_MODEL_LARGE }; extern enum m32r_model m32r_model; -#define TARGET_MODEL_SMALL (m32r_model == M32R_MODEL_SMALL) +#define TARGET_MODEL_SMALL (m32r_model == M32R_MODEL_SMALL) #define TARGET_MODEL_MEDIUM (m32r_model == M32R_MODEL_MEDIUM) -#define TARGET_MODEL_LARGE (m32r_model == M32R_MODEL_LARGE) -#define TARGET_ADDR24 (m32r_model == M32R_MODEL_SMALL) -#define TARGET_ADDR32 (! TARGET_ADDR24) -#define TARGET_CALL26 (! TARGET_CALL32) -#define TARGET_CALL32 (m32r_model == M32R_MODEL_LARGE) +#define TARGET_MODEL_LARGE (m32r_model == M32R_MODEL_LARGE) +#define TARGET_ADDR24 (m32r_model == M32R_MODEL_SMALL) +#define TARGET_ADDR32 (! TARGET_ADDR24) +#define TARGET_CALL26 (! TARGET_CALL32) +#define TARGET_CALL32 (m32r_model == M32R_MODEL_LARGE) /* The default is the small model. */ #ifndef M32R_MODEL_DEFAULT @@ -349,8 +382,7 @@ extern enum m32r_model m32r_model; .data). ??? There can be a problem if the user passes a -G value greater than the default and a library object in a header file is that size. The default is 8 so this should be rare - if it occurs the user - is required to rebuild the libraries or use a smaller value for -G. -*/ + is required to rebuild the libraries or use a smaller value for -G. */ /* Maximum size of variables that go in .sdata/.sbss. The -msdata=foo switch also controls how small variables are handled. */ @@ -361,9 +393,9 @@ extern enum m32r_model m32r_model; enum m32r_sdata { M32R_SDATA_NONE, M32R_SDATA_SDATA, M32R_SDATA_USE }; extern enum m32r_sdata m32r_sdata; -#define TARGET_SDATA_NONE (m32r_sdata == M32R_SDATA_NONE) +#define TARGET_SDATA_NONE (m32r_sdata == M32R_SDATA_NONE) #define TARGET_SDATA_SDATA (m32r_sdata == M32R_SDATA_SDATA) -#define TARGET_SDATA_USE (m32r_sdata == M32R_SDATA_USE) +#define TARGET_SDATA_USE (m32r_sdata == M32R_SDATA_USE) /* Default is to disable the SDA [for upward compatibility with previous toolchains]. */ @@ -438,11 +470,11 @@ extern enum m32r_sdata m32r_sdata; #define BITS_BIG_ENDIAN 1 /* Define this if most significant byte of a word is the lowest numbered. */ -#define BYTES_BIG_ENDIAN 1 +#define BYTES_BIG_ENDIAN (TARGET_LITTLE_ENDIAN == 0) /* Define this if most significant word of a multiword number is the lowest numbered. */ -#define WORDS_BIG_ENDIAN 1 +#define WORDS_BIG_ENDIAN (TARGET_LITTLE_ENDIAN == 0) /* Define this macro if WORDS_BIG_ENDIAN is not constant. This must be a constant value with the same meaning as WORDS_BIG_ENDIAN, @@ -481,7 +513,7 @@ extern enum m32r_sdata m32r_sdata; #define STACK_BOUNDARY 32 /* ALIGN FRAMES on word boundaries */ -#define M32R_STACK_ALIGN(LOC) (((LOC)+3) & ~3) +#define M32R_STACK_ALIGN(LOC) (((LOC) + 3) & ~ 3) /* Allocation boundary (in *bits*) for the code of a function. */ #define FUNCTION_BOUNDARY 32 @@ -516,6 +548,9 @@ extern enum m32r_sdata m32r_sdata; /* Set this nonzero if move instructions will actually fail to work when given unaligned data. */ #define STRICT_ALIGNMENT 1 + +/* Define LAVEL_ALIGN to calculate code length of PNOP at labels. */ +#define LABEL_ALIGN(insn) 2 /* Layout of source language data types. */ @@ -611,6 +646,14 @@ extern enum m32r_sdata m32r_sdata; #ifdef SUBTARGET_CONDITIONAL_REGISTER_USAGE #define CONDITIONAL_REGISTER_USAGE SUBTARGET_CONDITIONAL_REGISTER_USAGE +#else +#define CONDITIONAL_REGISTER_USAGE \ + do \ + { \ + if (flag_pic) \ + fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \ + } \ + while (0) #endif /* If defined, an initializer for a vector of integers, containing the @@ -621,7 +664,7 @@ extern enum m32r_sdata m32r_sdata; #define SUBTARGET_REG_ALLOC_ORDER #endif -#if 1 /* better for int code */ +#if 1 /* Better for int code. */ #define REG_ALLOC_ORDER \ { \ 4, 5, 6, 7, 2, 3, 8, 9, 10, \ @@ -629,7 +672,7 @@ extern enum m32r_sdata m32r_sdata; SUBTARGET_REG_ALLOC_ORDER \ } -#else /* better for fp code at expense of int code */ +#else /* Better for fp code at expense of int code. */ #define REG_ALLOC_ORDER \ { \ 0, 1, 2, 3, 4, 5, 6, 7, 8, \ @@ -643,13 +686,13 @@ extern enum m32r_sdata m32r_sdata; This is ordinarily the length in words of a value of mode MODE but can be less for certain modes in special long registers. */ #define HARD_REGNO_NREGS(REGNO, MODE) \ -((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) + ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */ extern const unsigned int m32r_hard_regno_mode_ok[FIRST_PSEUDO_REGISTER]; extern unsigned int m32r_mode_class[]; #define HARD_REGNO_MODE_OK(REGNO, MODE) \ -((m32r_hard_regno_mode_ok[REGNO] & m32r_mode_class[MODE]) != 0) + ((m32r_hard_regno_mode_ok[REGNO] & m32r_mode_class[MODE]) != 0) /* A C expression that is nonzero if it is desirable to choose register allocation so as to avoid move instructions between a @@ -660,11 +703,11 @@ extern unsigned int m32r_mode_class[]; MODE2)' must be zero. */ /* Tie QI/HI/SI modes together. */ -#define MODES_TIEABLE_P(MODE1, MODE2) \ -(GET_MODE_CLASS (MODE1) == MODE_INT \ - && GET_MODE_CLASS (MODE2) == MODE_INT \ - && GET_MODE_SIZE (MODE1) <= UNITS_PER_WORD \ - && GET_MODE_SIZE (MODE2) <= UNITS_PER_WORD) +#define MODES_TIEABLE_P(MODE1, MODE2) \ + ( GET_MODE_CLASS (MODE1) == MODE_INT \ + && GET_MODE_CLASS (MODE2) == MODE_INT \ + && GET_MODE_SIZE (MODE1) <= UNITS_PER_WORD \ + && GET_MODE_SIZE (MODE2) <= UNITS_PER_WORD) #define HARD_REGNO_RENAME_OK(OLD_REG, NEW_REG) \ m32r_hard_regno_rename_ok (OLD_REG, NEW_REG) @@ -745,10 +788,10 @@ extern enum reg_class m32r_regno_reg_class[FIRST_PSEUDO_REGISTER]; #define INDEX_REG_CLASS GENERAL_REGS #define BASE_REG_CLASS GENERAL_REGS -#define REG_CLASS_FROM_LETTER(C) \ -((C) == 'c' ? CARRY_REG \ - : (C) == 'a' ? ACCUM_REGS \ - : NO_REGS) +#define REG_CLASS_FROM_LETTER(C) \ + ( (C) == 'c' ? CARRY_REG \ + : (C) == 'a' ? ACCUM_REGS \ + : NO_REGS) /* 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 @@ -756,22 +799,22 @@ extern enum reg_class m32r_regno_reg_class[FIRST_PSEUDO_REGISTER]; Since they use reg_renumber, they are safe only once reg_renumber has been allocated, which happens in local-alloc.c. */ #define REGNO_OK_FOR_BASE_P(REGNO) \ -((REGNO) < FIRST_PSEUDO_REGISTER \ - ? GPR_P (REGNO) || (REGNO) == ARG_POINTER_REGNUM \ - : GPR_P (reg_renumber[REGNO])) + ((REGNO) < FIRST_PSEUDO_REGISTER \ + ? GPR_P (REGNO) || (REGNO) == ARG_POINTER_REGNUM \ + : GPR_P (reg_renumber[REGNO])) + #define REGNO_OK_FOR_INDEX_P(REGNO) REGNO_OK_FOR_BASE_P(REGNO) /* 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 on some machines in some cases it is preferable to use a more restrictive class. */ -#define PREFERRED_RELOAD_CLASS(X,CLASS) \ -(CLASS) +#define PREFERRED_RELOAD_CLASS(X,CLASS) (CLASS) /* Return the maximum number of consecutive registers needed to represent mode MODE in a register of class CLASS. */ #define CLASS_MAX_NREGS(CLASS, MODE) \ -((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) + ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) /* The letters I, J, K, L, M, N, O, P in a register constraint string can be used to stand for particular ranges of immediate operands. @@ -794,37 +837,37 @@ extern enum reg_class m32r_regno_reg_class[FIRST_PSEUDO_REGISTER]; <= ((unsigned HOST_WIDE_INT)((HIGH) - (LOW)))) /* Local to this file. */ -#define INT8_P(X) ((X) >= -0x80 && (X) <= 0x7f) -#define INT16_P(X) ((X) >= -0x8000 && (X) <= 0x7fff) -#define CMP_INT16_P(X) ((X) >= -0x7fff && (X) <= 0x8000) -#define UPPER16_P(X) (((X) & 0xffff) == 0 \ - && ((X) >> 16) >= -0x8000 \ - && ((X) >> 16) <= 0x7fff) -#define UINT16_P(X) (((unsigned HOST_WIDE_INT) (X)) <= 0x0000ffff) -#define UINT24_P(X) (((unsigned HOST_WIDE_INT) (X)) <= 0x00ffffff) -#define UINT32_P(X) (((unsigned HOST_WIDE_INT) (X)) <= 0xffffffff) -#define UINT5_P(X) ((X) >= 0 && (X) < 32) +#define INT8_P(X) ((X) >= - 0x80 && (X) <= 0x7f) +#define INT16_P(X) ((X) >= - 0x8000 && (X) <= 0x7fff) +#define CMP_INT16_P(X) ((X) >= - 0x7fff && (X) <= 0x8000) +#define UPPER16_P(X) (((X) & 0xffff) == 0 \ + && ((X) >> 16) >= - 0x8000 \ + && ((X) >> 16) <= 0x7fff) +#define UINT16_P(X) (((unsigned HOST_WIDE_INT) (X)) <= 0x0000ffff) +#define UINT24_P(X) (((unsigned HOST_WIDE_INT) (X)) <= 0x00ffffff) +#define UINT32_P(X) (((unsigned HOST_WIDE_INT) (X)) <= 0xffffffff) +#define UINT5_P(X) ((X) >= 0 && (X) < 32) #define INVERTED_SIGNED_8BIT(VAL) ((VAL) >= -127 && (VAL) <= 128) #define CONST_OK_FOR_LETTER_P(VALUE, C) \ -((C) == 'I' ? INT8_P (VALUE) \ - : (C) == 'J' ? INT16_P (VALUE) \ - : (C) == 'K' ? UINT16_P (VALUE) \ - : (C) == 'L' ? UPPER16_P (VALUE) \ - : (C) == 'M' ? UINT24_P (VALUE) \ - : (C) == 'N' ? INVERTED_SIGNED_8BIT (VALUE) \ - : (C) == 'O' ? UINT5_P (VALUE) \ - : (C) == 'P' ? CMP_INT16_P (VALUE) \ - : 0) + ( (C) == 'I' ? INT8_P (VALUE) \ + : (C) == 'J' ? INT16_P (VALUE) \ + : (C) == 'K' ? UINT16_P (VALUE) \ + : (C) == 'L' ? UPPER16_P (VALUE) \ + : (C) == 'M' ? UINT24_P (VALUE) \ + : (C) == 'N' ? INVERTED_SIGNED_8BIT (VALUE) \ + : (C) == 'O' ? UINT5_P (VALUE) \ + : (C) == 'P' ? CMP_INT16_P (VALUE) \ + : 0) /* Similar, but for floating constants, and defining letters G and H. Here VALUE is the CONST_DOUBLE rtx itself. For the m32r, handle a few constants inline. ??? We needn't treat DI and DF modes differently, but for now we do. */ -#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ -((C) == 'G' ? easy_di_const (VALUE) \ - : (C) == 'H' ? easy_df_const (VALUE) \ - : 0) +#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ + ( (C) == 'G' ? easy_di_const (VALUE) \ + : (C) == 'H' ? easy_df_const (VALUE) \ + : 0) /* A C expression that defines the optional machine-dependent constraint letters that can be used to segregate specific types of operands, @@ -839,19 +882,19 @@ extern enum reg_class m32r_regno_reg_class[FIRST_PSEUDO_REGISTER]; U is for loads with post increment. */ #define EXTRA_CONSTRAINT(VALUE, C) \ -( (C) == 'Q' ? ((TARGET_ADDR24 && GET_CODE (VALUE) == LABEL_REF) \ + ( (C) == 'Q' ? ((TARGET_ADDR24 && GET_CODE (VALUE) == LABEL_REF) \ || addr24_operand (VALUE, VOIDmode)) \ - : (C) == 'R' ? ((TARGET_ADDR32 && GET_CODE (VALUE) == LABEL_REF) \ + : (C) == 'R' ? ((TARGET_ADDR32 && GET_CODE (VALUE) == LABEL_REF) \ || addr32_operand (VALUE, VOIDmode)) \ - : (C) == 'S' ? (GET_CODE (VALUE) == MEM \ + : (C) == 'S' ? (GET_CODE (VALUE) == MEM \ && STORE_PREINC_PREDEC_P (GET_MODE (VALUE), \ XEXP (VALUE, 0))) \ - : (C) == 'T' ? (GET_CODE (VALUE) == MEM \ + : (C) == 'T' ? (GET_CODE (VALUE) == MEM \ && memreg_operand (VALUE, GET_MODE (VALUE))) \ - : (C) == 'U' ? (GET_CODE (VALUE) == MEM \ + : (C) == 'U' ? (GET_CODE (VALUE) == MEM \ && LOAD_POSTINC_P (GET_MODE (VALUE), \ XEXP (VALUE, 0))) \ - : 0) + : 0) /* Stack layout and stack pointer usage. */ @@ -859,12 +902,6 @@ extern enum reg_class m32r_regno_reg_class[FIRST_PSEUDO_REGISTER]; pointer to a smaller address. */ #define STACK_GROWS_DOWNWARD -/* Define this 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 from the frame pointer. */ -/*#define FRAME_GROWS_DOWNWARD*/ - /* Offset from frame pointer 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 @@ -872,7 +909,7 @@ extern enum reg_class m32r_regno_reg_class[FIRST_PSEUDO_REGISTER]; /* The frame pointer points at the same place as the stack pointer, except if alloca has been called. */ #define STARTING_FRAME_OFFSET \ -M32R_STACK_ALIGN (current_function_outgoing_args_size) + M32R_STACK_ALIGN (current_function_outgoing_args_size) /* Offset from the stack pointer register to the first location at which outgoing arguments are placed. */ @@ -881,32 +918,6 @@ M32R_STACK_ALIGN (current_function_outgoing_args_size) /* Offset of first parameter from the argument pointer register value. */ #define FIRST_PARM_OFFSET(FNDECL) 0 -/* A C expression whose value is RTL representing the address in a - stack frame where the pointer to the caller's frame is stored. - Assume that FRAMEADDR is an RTL expression for the address of the - stack frame itself. - - If you don't define this macro, the default is to return the value - of FRAMEADDR--that is, the stack frame address is also the address - of the stack word that points to the previous frame. */ -/*define DYNAMIC_CHAIN_ADDRESS (FRAMEADDR)*/ - -/* A C expression whose value is RTL representing the value of the - return address for the frame COUNT steps up from the current frame. - FRAMEADDR is the frame pointer of the COUNT frame, or the frame - pointer of the COUNT - 1 frame if `RETURN_ADDR_IN_PREVIOUS_FRAME' - is defined. */ -/* The current return address is in r14. */ -#if 0 /* The default value should work. */ -#define RETURN_ADDR_RTX(COUNT, FRAME) \ -(((COUNT) == -1) \ - ? gen_rtx_REG (Pmode, 14) \ - : copy_to_reg (gen_rtx_MEM (Pmode, \ - memory_address (Pmode, \ - plus_constant ((FRAME), \ - UNITS_PER_WORD))))) -#endif - /* Register to use for pushing function arguments. */ #define STACK_POINTER_REGNUM 15 @@ -916,30 +927,17 @@ M32R_STACK_ALIGN (current_function_outgoing_args_size) /* Base register for access to arguments of the function. */ #define ARG_POINTER_REGNUM 16 -/* The register number of the return address pointer register, which - is used to access the current function's return address from the - stack. On some machines, the return address is not at a fixed - offset from the frame pointer or stack pointer or argument - pointer. This register can be defined to point to the return - address on the stack, and then be converted by `ELIMINABLE_REGS' - into either the frame pointer or stack pointer. - - Do not define this macro unless there is no other way to get the - return address from the stack. */ -/* ??? revisit */ -/* #define RETURN_ADDRESS_POINTER_REGNUM */ - -/* Register in which static-chain is passed to a function. This must - not be a register used by the prologue. */ -#define STATIC_CHAIN_REGNUM 7 +/* Register in which static-chain is passed to a function. + This must not be a register used by the prologue. */ +#define STATIC_CHAIN_REGNUM 7 /* These aren't official macros. */ -#define PROLOGUE_TMP_REGNUM 4 -#define RETURN_ADDR_REGNUM 14 -/* #define GP_REGNUM 12 */ -#define CARRY_REGNUM 17 -#define ACCUM_REGNUM 18 -#define M32R_MAX_INT_REGS 16 +#define PROLOGUE_TMP_REGNUM 4 +#define RETURN_ADDR_REGNUM 14 +/* #define GP_REGNUM 12 */ +#define CARRY_REGNUM 17 +#define ACCUM_REGNUM 18 +#define M32R_MAX_INT_REGS 16 #ifndef SUBTARGET_GPR_P #define SUBTARGET_GPR_P(REGNO) 0 @@ -1004,19 +1002,21 @@ M32R_STACK_ALIGN (current_function_outgoing_args_size) registers. This macro must be defined if `ELIMINABLE_REGS' is defined. */ -#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ -{ \ - int size = m32r_compute_frame_size (get_frame_size ()); \ - \ - if ((FROM) == FRAME_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \ - (OFFSET) = 0; \ - else if ((FROM) == ARG_POINTER_REGNUM && (TO) == FRAME_POINTER_REGNUM) \ - (OFFSET) = size - current_function_pretend_args_size; \ - else if ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \ - (OFFSET) = size - current_function_pretend_args_size; \ - else \ - abort (); \ -} +#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ + do \ + { \ + int size = m32r_compute_frame_size (get_frame_size ()); \ + \ + if ((FROM) == FRAME_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \ + (OFFSET) = 0; \ + else if ((FROM) == ARG_POINTER_REGNUM && (TO) == FRAME_POINTER_REGNUM) \ + (OFFSET) = size - current_function_pretend_args_size; \ + else if ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \ + (OFFSET) = size - current_function_pretend_args_size; \ + else \ + abort (); \ + } \ + while (0) /* Function argument passing. */ @@ -1030,22 +1030,6 @@ M32R_STACK_ALIGN (current_function_outgoing_args_size) increase the stack frame size by this amount. */ #define ACCUMULATE_OUTGOING_ARGS 1 -/* Define this macro if functions should assume that stack space has - been allocated for arguments even when their values are passed in - registers. - - The value of this macro is the size, in bytes, of the area - reserved for arguments passed in registers for the function - represented by FNDECL. - - This space can be allocated by the caller, or be a part of the - machine-dependent stack frame: `OUTGOING_REG_PARM_STACK_SPACE' says - which. */ -#if 0 -#define REG_PARM_STACK_SPACE(FNDECL) \ - (M32R_MAX_PARM_REGS * UNITS_PER_WORD) -#endif - /* Value is the number of bytes of arguments automatically popped when returning from a subroutine call. FUNDECL is the declaration node of the function (as a tree), @@ -1159,9 +1143,8 @@ M32R_STACK_ALIGN (current_function_outgoing_args_size) #if 0 /* We assume PARM_BOUNDARY == UNITS_PER_WORD here. */ #define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \ -(((TYPE) ? TYPE_ALIGN (TYPE) : GET_MODE_BITSIZE (MODE)) <= PARM_BOUNDARY \ - ? PARM_BOUNDARY \ - : 2 * PARM_BOUNDARY) + (((TYPE) ? TYPE_ALIGN (TYPE) : GET_MODE_BITSIZE (MODE)) <= PARM_BOUNDARY \ + ? PARM_BOUNDARY : 2 * PARM_BOUNDARY) #endif /* This macro offers an alternative @@ -1192,7 +1175,7 @@ M32R_STACK_ALIGN (current_function_outgoing_args_size) this case. */ #define SETUP_INCOMING_VARARGS(ARGS_SO_FAR, MODE, TYPE, PRETEND_SIZE, NO_RTL) \ - m32r_setup_incoming_varargs (&ARGS_SO_FAR, MODE, TYPE, &PRETEND_SIZE, NO_RTL) + m32r_setup_incoming_varargs (& ARGS_SO_FAR, MODE, TYPE, & PRETEND_SIZE, NO_RTL) /* Implement `va_arg'. */ #define EXPAND_BUILTIN_VA_ARG(valist, type) \ @@ -1243,19 +1226,49 @@ M32R_STACK_ALIGN (current_function_outgoing_args_size) /* Output assembler code to FILE to increment profiler label # LABELNO for profiling a function entry. */ -#define FUNCTION_PROFILER(FILE, LABELNO) abort () +#undef FUNCTION_PROFILER +#define FUNCTION_PROFILER(FILE, LABELNO) \ + do \ + { \ + if (flag_pic) \ + { \ + fprintf (FILE, "\tld24 r14,#mcount\n"); \ + fprintf (FILE, "\tadd r14,r12\n"); \ + fprintf (FILE, "\tld r14,@r14\n"); \ + fprintf (FILE, "\tjl r14\n"); \ + } \ + else \ + { \ + if (TARGET_ADDR24) \ + fprintf (FILE, "\tbl mcount\n"); \ + else \ + { \ + fprintf (FILE, "\tseth r14,#high(mcount)\n"); \ + fprintf (FILE, "\tor3 r14,r14,#low(mcount)\n"); \ + fprintf (FILE, "\tjl r14\n"); \ + } \ + } \ + fprintf (FILE, "\taddi sp,#4\n"); \ + } \ + while (0) /* Trampolines. */ -/* On the M32R, the trampoline is +/* On the M32R, the trampoline is: - ld24 r7,STATIC - ld24 r6,FUNCTION - jmp r6 - nop + mv r7, lr -> bl L1 ; 178e 7e01 +L1: add3 r6, lr, #L2-L1 ; 86ae 000c (L2 - L1 = 12) + mv lr, r7 -> ld r7,@r6+ ; 1e87 27e6 + ld r6, @r6 -> jmp r6 ; 26c6 1fc6 +L2: .word STATIC + .word FUNCTION */ - ??? Need addr32 support. -*/ +#ifndef CACHE_FLUSH_FUNC +#define CACHE_FLUSH_FUNC "_flush_cache" +#endif +#ifndef CACHE_FLUSH_TRAP +#define CACHE_FLUSH_TRAP "12" +#endif /* Length in bytes of the trampoline for entering a nested function. */ #define TRAMPOLINE_SIZE 12 @@ -1263,16 +1276,35 @@ M32R_STACK_ALIGN (current_function_outgoing_args_size) /* Emit RTL insns to initialize the variable parts of a trampoline. FNADDR is an RTX for the address of the function's pure code. CXT is an RTX for the static chain value for the function. */ -#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ -do { \ - emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 0)), \ - plus_constant ((CXT), 0xe7000000)); \ - emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 4)), \ - plus_constant ((FNADDR), 0xe6000000)); \ - emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 8)), \ - GEN_INT (0x1fc67000)); \ - emit_insn (gen_flush_icache (validize_mem (gen_rtx_MEM (SImode, TRAMP)))); \ -} while (0) +#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ + do \ + { \ + emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 0)), \ + GEN_INT \ + (TARGET_LITTLE_ENDIAN ? 0x017e8e17 : 0x178e7e01)); \ + emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 4)), \ + GEN_INT \ + (TARGET_LITTLE_ENDIAN ? 0x0c00ae86 : 0x86ae000c)); \ + emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 8)), \ + GEN_INT \ + (TARGET_LITTLE_ENDIAN ? 0xe627871e : 0x1e8727e6)); \ + emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 12)), \ + GEN_INT \ + (TARGET_LITTLE_ENDIAN ? 0xc616c626 : 0x26c61fc6)); \ + emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 16)), \ + (CXT)); \ + emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 20)), \ + (FNADDR)); \ + if (m32r_cache_flush_trap_string && m32r_cache_flush_trap_string[0]) \ + emit_insn (gen_flush_icache (validize_mem (gen_rtx_MEM (SImode, TRAMP)),\ + GEN_INT (m32r_cache_flush_trap) )); \ + else if (m32r_cache_flush_func && m32r_cache_flush_func[0]) \ + emit_library_call (gen_rtx_SYMBOL_REF (Pmode, m32r_cache_flush_func), \ + 0, VOIDmode, 3, TRAMP, Pmode, \ + GEN_INT (TRAMPOLINE_SIZE), SImode, \ + GEN_INT (3), SImode); \ + } \ + while (0) /* Library calls. */ @@ -1286,14 +1318,17 @@ do { \ /* We have post-inc load and pre-dec,pre-inc store, but only for 4 byte vals. */ -#define HAVE_PRE_DECREMENT 1 -#define HAVE_PRE_INCREMENT 1 +#define HAVE_PRE_DECREMENT 1 +#define HAVE_PRE_INCREMENT 1 #define HAVE_POST_INCREMENT 1 /* Recognize any constant value that is a valid address. */ -#define CONSTANT_ADDRESS_P(X) \ -(GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \ - || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST) +#define CONSTANT_ADDRESS_P(X) \ + ( GET_CODE (X) == LABEL_REF \ + || GET_CODE (X) == SYMBOL_REF \ + || GET_CODE (X) == CONST_INT \ + || (GET_CODE (X) == CONST \ + && ! (flag_pic && ! m32r_legitimate_pic_operand_p (X)))) /* Nonzero if the constant value X is a legitimate general operand. We don't allow (plus symbol large-constant) as the relocations can't @@ -1302,11 +1337,11 @@ do { \ constant to memory if they can't handle them. */ #define LEGITIMATE_CONSTANT_P(X) \ -(! (GET_CODE (X) == CONST \ - && GET_CODE (XEXP (X, 0)) == PLUS \ - && GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF \ - && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \ - && (unsigned HOST_WIDE_INT) INTVAL (XEXP (XEXP (X, 0), 1)) > 32767)) + (! (GET_CODE (X) == CONST \ + && GET_CODE (XEXP (X, 0)) == PLUS \ + && GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF \ + && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \ + && (unsigned HOST_WIDE_INT) INTVAL (XEXP (XEXP (X, 0), 1)) > 32767)) /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx and check its validity for a certain class. @@ -1333,9 +1368,9 @@ do { \ /* 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) \ -(GPR_P (REGNO (X)) \ - || (REGNO (X)) == ARG_POINTER_REGNUM \ - || REGNO (X) >= FIRST_PSEUDO_REGISTER) + (GPR_P (REGNO (X)) \ + || (REGNO (X)) == ARG_POINTER_REGNUM \ + || REGNO (X) >= FIRST_PSEUDO_REGISTER) /* 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) @@ -1352,51 +1387,54 @@ do { \ /* Local to this file. */ #define RTX_OK_FOR_OFFSET_P(X) \ -(GET_CODE (X) == CONST_INT && INT16_P (INTVAL (X))) + (GET_CODE (X) == CONST_INT && INT16_P (INTVAL (X))) /* Local to this file. */ -#define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X) \ -(GET_CODE (X) == PLUS \ - && RTX_OK_FOR_BASE_P (XEXP (X, 0)) \ - && RTX_OK_FOR_OFFSET_P (XEXP (X, 1))) +#define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X) \ + (GET_CODE (X) == PLUS \ + && RTX_OK_FOR_BASE_P (XEXP (X, 0)) \ + && RTX_OK_FOR_OFFSET_P (XEXP (X, 1))) /* Local to this file. */ /* For LO_SUM addresses, do not allow them if the MODE is > 1 word, since more than one instruction will be required. */ -#define LEGITIMATE_LO_SUM_ADDRESS_P(MODE, X) \ -(GET_CODE (X) == LO_SUM \ - && (MODE != BLKmode && GET_MODE_SIZE (MODE) <= UNITS_PER_WORD) \ - && RTX_OK_FOR_BASE_P (XEXP (X, 0)) \ - && CONSTANT_P (XEXP (X, 1))) +#define LEGITIMATE_LO_SUM_ADDRESS_P(MODE, X) \ + (GET_CODE (X) == LO_SUM \ + && (MODE != BLKmode && GET_MODE_SIZE (MODE) <= UNITS_PER_WORD)\ + && RTX_OK_FOR_BASE_P (XEXP (X, 0)) \ + && CONSTANT_P (XEXP (X, 1))) /* Local to this file. */ /* Is this a load and increment operation. */ -#define LOAD_POSTINC_P(MODE, X) \ -(((MODE) == SImode || (MODE) == SFmode) \ - && GET_CODE (X) == POST_INC \ - && GET_CODE (XEXP (X, 0)) == REG \ - && RTX_OK_FOR_BASE_P (XEXP (X, 0))) +#define LOAD_POSTINC_P(MODE, X) \ + (((MODE) == SImode || (MODE) == SFmode) \ + && GET_CODE (X) == POST_INC \ + && GET_CODE (XEXP (X, 0)) == REG \ + && RTX_OK_FOR_BASE_P (XEXP (X, 0))) /* Local to this file. */ /* Is this an increment/decrement and store operation. */ -#define STORE_PREINC_PREDEC_P(MODE, X) \ -(((MODE) == SImode || (MODE) == SFmode) \ - && (GET_CODE (X) == PRE_INC || GET_CODE (X) == PRE_DEC) \ - && GET_CODE (XEXP (X, 0)) == REG \ - && RTX_OK_FOR_BASE_P (XEXP (X, 0))) - -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ -{ if (RTX_OK_FOR_BASE_P (X)) \ - goto ADDR; \ - if (LEGITIMATE_OFFSET_ADDRESS_P ((MODE), (X))) \ - goto ADDR; \ - if (LEGITIMATE_LO_SUM_ADDRESS_P ((MODE), (X))) \ - goto ADDR; \ - if (LOAD_POSTINC_P ((MODE), (X))) \ - goto ADDR; \ - if (STORE_PREINC_PREDEC_P ((MODE), (X))) \ - goto ADDR; \ -} +#define STORE_PREINC_PREDEC_P(MODE, X) \ + (((MODE) == SImode || (MODE) == SFmode) \ + && (GET_CODE (X) == PRE_INC || GET_CODE (X) == PRE_DEC) \ + && GET_CODE (XEXP (X, 0)) == REG \ + && RTX_OK_FOR_BASE_P (XEXP (X, 0))) + +#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ + do \ + { \ + if (RTX_OK_FOR_BASE_P (X)) \ + goto ADDR; \ + if (LEGITIMATE_OFFSET_ADDRESS_P ((MODE), (X))) \ + goto ADDR; \ + if (LEGITIMATE_LO_SUM_ADDRESS_P ((MODE), (X))) \ + goto ADDR; \ + if (LOAD_POSTINC_P ((MODE), (X))) \ + goto ADDR; \ + if (STORE_PREINC_PREDEC_P ((MODE), (X))) \ + goto ADDR; \ + } \ + while (0) /* Try machine-dependent ways of modifying an illegitimate address to be legitimate. If we find one, return the new, valid address. @@ -1409,22 +1447,30 @@ do { \ GO_IF_LEGITIMATE_ADDRESS. It is always safe for this macro to do nothing. It exists to recognize - opportunities to optimize the output. - - ??? Is there anything useful we can do here for the M32R? */ - -#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) + opportunities to optimize the output. */ + +#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \ + do \ + { \ + if (flag_pic) \ + (X) = m32r_legitimize_pic_address (X, NULL_RTX); \ + 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 GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \ -do { \ - if (GET_CODE (ADDR) == PRE_DEC \ - || GET_CODE (ADDR) == PRE_INC \ - || GET_CODE (ADDR) == POST_INC \ - || GET_CODE (ADDR) == LO_SUM) \ - goto LABEL; \ -} while (0) +#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \ + do \ + { \ + if ( GET_CODE (ADDR) == PRE_DEC \ + || GET_CODE (ADDR) == PRE_INC \ + || GET_CODE (ADDR) == POST_INC \ + || GET_CODE (ADDR) == LO_SUM) \ + goto LABEL; \ + } \ + while (0) /* Condition code usage. */ @@ -1481,9 +1527,9 @@ do { \ output in the text section, along with the assembler instructions. Otherwise, the readonly data section is used. This macro is irrelevant if there is no separate readonly data section. */ -/*#define JUMP_TABLES_IN_TEXT_SECTION*/ +#define JUMP_TABLES_IN_TEXT_SECTION (flag_pic) -/* PIC */ +/* Position Independent Code. */ /* The register number of the register used to address a table of static data addresses in memory. In some cases this register is defined by a @@ -1492,7 +1538,7 @@ do { \ pointer and frame pointer registers. If this macro is not defined, it is up to the machine-dependent files to allocate such a register (if necessary). */ -/*#define PIC_OFFSET_TABLE_REGNUM 12*/ +#define PIC_OFFSET_TABLE_REGNUM 12 /* Define this macro if the register defined by PIC_OFFSET_TABLE_REGNUM is clobbered by calls. Do not define this macro if PIC_OFFSET_TABLE_REGNUM @@ -1514,7 +1560,7 @@ do { \ included in functions which used inline functions and were compiled to assembly language.) */ -/*#define FINALIZE_PIC m32r_finalize_pic ()*/ +#define FINALIZE_PIC m32r_finalize_pic () /* A C expression that is nonzero if X is a legitimate immediate operand on the target machine when generating position independent code. @@ -1523,7 +1569,7 @@ do { \ check it either. You need not define this macro if all constants (including SYMBOL_REF) can be immediate operands when generating position independent code. */ -/*#define LEGITIMATE_PIC_OPERAND_P(X)*/ +#define LEGITIMATE_PIC_OPERAND_P(X) m32r_legitimate_pic_operand_p (X) /* Control the assembler format that we output. */ @@ -1620,10 +1666,10 @@ extern char m32r_punct_chars[256]; are useful when a single `md' file must support multiple assembler formats. In that case, the various `tm.h' files can define these macros differently. */ -#define REGISTER_PREFIX "" -#define LOCAL_LABEL_PREFIX ".L" -#define USER_LABEL_PREFIX "" -#define IMMEDIATE_PREFIX "#" +#define REGISTER_PREFIX "" +#define LOCAL_LABEL_PREFIX ".L" +#define USER_LABEL_PREFIX "" +#define IMMEDIATE_PREFIX "#" /* This is how to output an element of a case-vector that is absolute. */ #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ @@ -1648,7 +1694,7 @@ extern char m32r_punct_chars[256]; fprintf (FILE, "-"); \ ASM_GENERATE_INTERNAL_LABEL (label, "L", REL); \ assemble_name (FILE, label); \ - fprintf (FILE, ")\n"); \ + fprintf (FILE, "\n"); \ } \ while (0) @@ -1720,7 +1766,7 @@ extern char m32r_punct_chars[256]; /* Debugging information. */ /* Generate DBX and DWARF debugging information. */ -#define DBX_DEBUGGING_INFO 1 +#define DBX_DEBUGGING_INFO 1 #define DWARF2_DEBUGGING_INFO 1 /* Prefer STABS (for now). */ @@ -1734,7 +1780,7 @@ extern char m32r_punct_chars[256]; /* Specify the machine mode that this machine uses for the index in the tablejump instruction. */ -#define CASE_VECTOR_MODE Pmode +#define CASE_VECTOR_MODE (flag_pic ? SImode : Pmode) /* Define as C expression which evaluates to nonzero if the tablejump instruction expects the table to contain offsets from the address of the @@ -1755,8 +1801,8 @@ extern char m32r_punct_chars[256]; done, NIL if none. */ #define LOAD_EXTEND_OP(MODE) ZERO_EXTEND -/* Max number of bytes we can move from memory to memory - in one reasonably fast instruction. */ +/* Max number of bytes we can move from memory + to memory in one reasonably fast instruction. */ #define MOVE_MAX 4 /* Define this to be nonzero if shift instructions ignore all but the low-order diff --git a/gcc/config/m32r/m32r.md b/gcc/config/m32r/m32r.md index 4c9bb6f..5e562a7 100644 --- a/gcc/config/m32r/m32r.md +++ b/gcc/config/m32r/m32r.md @@ -297,6 +297,18 @@ "" " { + /* Fixup PIC cases. */ + if (flag_pic) + { + if (symbolic_operand (operands[1], QImode)) + { + if (reload_in_progress || reload_completed) + operands[1] = m32r_legitimize_pic_address (operands[1], operands[0]); + else + operands[1] = m32r_legitimize_pic_address (operands[1], NULL_RTX); + } + } + /* Everything except mem = const or mem = mem can be done easily. Objects in the small data area are handled too. */ @@ -325,6 +337,18 @@ "" " { + /* Fixup PIC cases. */ + if (flag_pic) + { + if (symbolic_operand (operands[1], HImode)) + { + if (reload_in_progress || reload_completed) + operands[1] = m32r_legitimize_pic_address (operands[1], operands[0]); + else + operands[1] = m32r_legitimize_pic_address (operands[1], NULL_RTX); + } + } + /* Everything except mem = const or mem = mem can be done easily. */ if (GET_CODE (operands[0]) == MEM) @@ -365,6 +389,18 @@ "" " { + /* Fixup PIC cases. */ + if (flag_pic) + { + if (symbolic_operand (operands[1], SImode)) + { + if (reload_in_progress || reload_completed) + operands[1] = m32r_legitimize_pic_address (operands[1], operands[0]); + else + operands[1] = m32r_legitimize_pic_address (operands[1], NULL_RTX); + } + } + /* Everything except mem = const or mem = mem can be done easily. */ if (GET_CODE (operands[0]) == MEM) @@ -590,6 +626,18 @@ "" " { + /* Fixup PIC cases. */ + if (flag_pic) + { + if (symbolic_operand (operands[1], DImode)) + { + if (reload_in_progress || reload_completed) + operands[1] = m32r_legitimize_pic_address (operands[1], operands[0]); + else + operands[1] = m32r_legitimize_pic_address (operands[1], NULL_RTX); + } + } + /* Everything except mem = const or mem = mem can be done easily. */ if (GET_CODE (operands[0]) == MEM) @@ -619,6 +667,18 @@ "" " { + /* Fixup PIC cases. */ + if (flag_pic) + { + if (symbolic_operand (operands[1], SFmode)) + { + if (reload_in_progress || reload_completed) + operands[1] = m32r_legitimize_pic_address (operands[1], operands[0]); + else + operands[1] = m32r_legitimize_pic_address (operands[1], NULL_RTX); + } + } + /* Everything except mem = const or mem = mem can be done easily. */ if (GET_CODE (operands[0]) == MEM) @@ -659,6 +719,18 @@ "" " { + /* Fixup PIC cases. */ + if (flag_pic) + { + if (symbolic_operand (operands[1], DFmode)) + { + if (reload_in_progress || reload_completed) + operands[1] = m32r_legitimize_pic_address (operands[1], operands[0]); + else + operands[1] = m32r_legitimize_pic_address (operands[1], NULL_RTX); + } + } + /* Everything except mem = const or mem = mem can be done easily. */ if (GET_CODE (operands[0]) == MEM) @@ -2269,7 +2341,27 @@ [(set_attr "type" "uncond_branch") (set_attr "length" "2")]) -(define_insn "tablejump" +(define_expand "tablejump" + [(parallel [(set (pc) (match_operand 0 "register_operand" "r")) + (use (label_ref (match_operand 1 "" "")))])] + "" + " +{ + /* In pic mode, our address differences are against the base of the + table. Add that base value back in; CSE ought to be able to combine + the two address loads. */ + if (flag_pic) + { + rtx tmp, tmp2; + + tmp = gen_rtx_LABEL_REF (Pmode, operands[1]); + tmp2 = operands[0]; + tmp = gen_rtx_PLUS (Pmode, tmp2, tmp); + operands[0] = memory_address (Pmode, tmp); + } +}") + +(define_insn "*tablejump_insn" [(set (pc) (match_operand:SI 0 "address_operand" "p")) (use (label_ref (match_operand 1 "" "")))] "" @@ -2284,7 +2376,11 @@ (match_operand 1 "" "")) (clobber (reg:SI 14))])] "" - "") + " +{ + if (flag_pic) + current_function_uses_pic_offset_table = 1; +}") (define_insn "*call_via_reg" [(call (mem:SI (match_operand:SI 0 "register_operand" "r")) @@ -2335,7 +2431,11 @@ (match_operand 2 "" ""))) (clobber (reg:SI 14))])] "" - "") + " +{ + if (flag_pic) + current_function_uses_pic_offset_table = 1; +}") (define_insn "*call_value_via_reg" [(set (match_operand 0 "register_operand" "=r") @@ -2357,6 +2457,9 @@ { int call26_p = call26_operand (operands[1], FUNCTION_MODE); + if (flag_pic) + current_function_uses_pic_offset_table = 1; + if (! call26_p) { /* We may not be able to reach with a `bl' insn so punt and leave it to @@ -2398,11 +2501,13 @@ ;; Special pattern to flush the icache. (define_insn "flush_icache" - [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 0)] + [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 0) + (match_operand 1 "" "") + (clobber (reg:SI 17))] "" - "* return \"nop ; flush-icache\";" - [(set_attr "type" "int2") - (set_attr "length" "2")]) + "* return \"trap %#%1 ; flush-icache\";" + [(set_attr "type" "int4") + (set_attr "length" "4")]) ;; Speed up fabs and provide correct sign handling for -0 @@ -2581,3 +2686,44 @@ "* m32r_output_block_move (insn, operands); return \"\"; " [(set_attr "type" "store8") (set_attr "length" "72")]) ;; Maximum + +;; PIC + +/* 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. */ + +(define_insn "pic_load_addr" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand 1 "" "")] 4))] + "flag_pic" + "ld24 %0,%#%1" + [(set_attr "type" "int4")]) + +;; Load program counter insns. + +(define_insn "get_pc" + [(clobber (reg:SI 14)) + (set (match_operand 0 "register_operand" "=r") + (unspec [(match_operand 1 "" "")] 5)) + (use (match_operand:SI 2 "immediate_operand" ""))] + "flag_pic" + "* +{ + if (INTVAL(operands[2])) + return \"bl.s .+4\;ld24 %0,%#%1\;add %0,lr\"; + else + return \"bl.s .+4\;seth %0,%#shigh(%1)\;add3 %0,%0,%#low(%1+4)\;add %0,lr\";}" + [(set (attr "length") (if_then_else (ne (match_dup 2) (const_int 0)) + (const_int 8) + (const_int 12)))]) + +(define_expand "builtin_setjmp_receiver" + [(label_ref (match_operand 0 "" ""))] + "flag_pic" + " +{ + m32r_load_pic_register (); + DONE; +}") diff --git a/gcc/config/m32r/t-linux b/gcc/config/m32r/t-linux new file mode 100644 index 0000000..0304657 --- /dev/null +++ b/gcc/config/m32r/t-linux @@ -0,0 +1,42 @@ +# lib1funcs.asm is currently empty. +CROSS_LIBGCC1 = + +# These are really part of libgcc1, but this will cause them to be +# built correctly, so... + +LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c + +# Turn off the SDA while compiling libgcc2. There are no headers for it +# and we want maximal upward compatibility here. + +TARGET_LIBGCC2_CFLAGS = -G 0 -fPIC + +fp-bit.c: $(srcdir)/config/fp-bit.c + echo '#define FLOAT' > fp-bit.c + cat $(srcdir)/config/fp-bit.c >> fp-bit.c + +dp-bit.c: $(srcdir)/config/fp-bit.c + cat $(srcdir)/config/fp-bit.c > dp-bit.c + +# We need to use -fpic when we are using gcc to compile the routines in +# initfini.c. This is only really needed when we are going to use gcc/g++ +# to produce a shared library, but since we don't know ahead of time when +# we will be doing that, we just always use -fpic when compiling the +# routines in initfini.c. +# -fpic currently isn't supported for the m32r. + +CRTSTUFF_T_CFLAGS_S = -fPIC + + +# Don't run fixproto +STMP_FIXPROTO = + +# Don't install "assert.h" in gcc. We use the one in glibc. +INSTALL_ASSERT_H = + +# Do not build libgcc1. Let gcc generate those functions. The GNU/Linux +# C library can handle them. +LIBGCC1 = +CROSS_LIBGCC1 = +LIBGCC1_TEST = + diff --git a/gcc/config/m32r/xm-linux.h b/gcc/config/m32r/xm-linux.h new file mode 100644 index 0000000..1c6f462 --- /dev/null +++ b/gcc/config/m32r/xm-linux.h @@ -0,0 +1,26 @@ +/* Configuration for GCC for Renesas M32R running Linux-based GNU systems. + Copyright (C) 2003 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING. If not, write to the + Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. */ + +#include <m32r/xm-m32r.h> +#include <xm-linux.h> + +/* Doubles are stored in memory with the high order word first. + This matters when cross-compiling. */ +#undef HOST_WORDS_BIG_ENDIAN diff --git a/gcc/config/m32r/xm-m32r.h b/gcc/config/m32r/xm-m32r.h new file mode 100644 index 0000000..5859449 --- /dev/null +++ b/gcc/config/m32r/xm-m32r.h @@ -0,0 +1,43 @@ +/* Configuration for GNU C-compiler for the M32R processor. + Copyright (C) 2003 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING. If not, write to the + Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. */ + +/* This describes the machine the compiler is hosted on. */ +#define HOST_BITS_PER_CHAR 8 +#define HOST_BITS_PER_SHORT 16 +#define HOST_BITS_PER_INT 32 +#define HOST_BITS_PER_LONG 32 +#define HOST_BITS_PER_LONGLONG 64 + +/* Doubles are stored in memory with the high order word first. + This matters when cross-compiling. */ +#define HOST_WORDS_BIG_ENDIAN 1 + +/* target machine dependencies. + tm.h is a symbolic link to the actual target specific file. */ +#include "tm.h" + +/* Arguments to use with `exit'. */ +#define SUCCESS_EXIT_CODE 0 +#define FATAL_EXIT_CODE 33 + +/* If compiled with Sun CC, the use of alloca requires this #include. */ +#ifndef __GNUC__ +#include "alloca.h" +#endif diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 7e48a3b..d634362 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -400,8 +400,16 @@ in the following sections. -mno-crt0 -mrelax} @emph{M32R/D Options} -@gccoptlist{-m32r2 -m32rx -m32r -mcode-model=@var{model-type} @gol --msdata=@var{sdata-type} -G @var{num}} +@gccoptlist{-m32r2 -m32rx -m32r @gol +-mdebug @gol +-malign-loops -mno-align-loops @gol +-missue-rate=@var{number} @gol +-mbranch-cost=@var{number} @gol +-mmodel=@var{code-size-model-type} @gol +-msdata=@var{sdata-type} @gol +-mno-flush-func -mflush-func=@var{name} @gol +-mno-flush-trap -mflush-trap=@var{number} @gol +-G @var{num}} @emph{M88K Options} @gccoptlist{-m88000 -m88100 -m88110 -mbig-pic @gol @@ -6834,8 +6842,8 @@ Generate code for the M32R/X@. @opindex m32r Generate code for the M32R@. This is the default. -@item -mcode-model=small -@opindex mcode-model=small +@item -mmodel=small +@opindex mmodel=small Assume all objects live in the lower 16MB of memory (so that their addresses can be loaded with the @code{ld24} instruction), and assume all subroutines are reachable with the @code{bl} instruction. @@ -6844,14 +6852,14 @@ This is the default. The addressability of a particular object can be set with the @code{model} attribute. -@item -mcode-model=medium -@opindex mcode-model=medium +@item -mmodel=medium +@opindex mmodel=medium Assume objects may be anywhere in the 32-bit address space (the compiler will generate @code{seth/add3} instructions to load their addresses), and assume all subroutines are reachable with the @code{bl} instruction. -@item -mcode-model=large -@opindex mcode-model=large +@item -mmodel=large +@opindex mmodel=large Assume objects may be anywhere in the 32-bit address space (the compiler will generate @code{seth/add3} instructions to load their addresses), and assume subroutines may not be reachable with the @code{bl} instruction @@ -6893,6 +6901,49 @@ Compiling with different values of @var{num} may or may not work; if it doesn't the linker will give an error message---incorrect code will not be generated. +@item -mdebug +@opindex -mdebug +Makes the M32R specific code in the compiler display some statistics +that might help in debugging programs. + +@item -malign-loops +@opindex +Align all loops to a 32-byte boundary. + +@item -mno-align-loops +@opindex +Do not enforce a 32-byte alignment for loops. This is the default. + +@item -missue-rate=@var{number} +@opindex +Issue @var{number} instructions per cycle. @var{number} can only be 1 +or 2. + +@item -mbranch-cost=@var{number} +@opindex +@var{number} can only be 1 or 2. If it is 1 then branches will be +prefered over conditional code, if it is 2, then the opposite will +apply. + +@item -mflush-trap=@var{number} +@opindex +Specifies the trap number to use to flush the cache. The default is +12. Valid numbers are between 0 and 15 inclusive. + +@item -mno-flush-trap +@opindex +Specifies that the cache cannot be flushed by using a trap. + +@item -mflush-func=@var{name} +@opindex +Specifies the name of the operating system function to call to flush +the cache. The default is @emph{_flush_cache}, but a function call +will only be used if a trap is not available. + +@item -mno-flush-func +@opindex +Indicates that there is no OS function for flushing the cache. + @end table @node M88K Options |